From 7dc7ed97eb87f034ac9c24c5ab5d568987b08bc7 Mon Sep 17 00:00:00 2001 From: Pxl Date: Mon, 5 Jun 2023 10:48:07 +0800 Subject: [PATCH] [Chore](build) remove some unused code and remove some wno (#20326) remove some unused code about spinlock remove some wno and fix warning remove varadic macro usage --- LICENSE.txt | 40 - be/CMakeLists.txt | 13 +- be/src/agent/task_worker_pool.cpp | 5 +- be/src/agent/user_resource_listener.cpp | 5 +- be/src/common/logging.h | 38 +- be/src/gutil/CMakeLists.txt | 1 - be/src/gutil/dynamic_annotations.c | 44 - be/src/gutil/dynamic_annotations.h | 30 - be/src/gutil/linux_syscall_support.h | 2777 ------------ be/src/gutil/spinlock_internal.cc | 125 - be/src/gutil/spinlock_internal.h | 61 - be/src/gutil/spinlock_linux-inl.h | 98 - be/src/gutil/spinlock_posix-inl.h | 61 - be/src/gutil/spinlock_win32-inl.h | 52 - be/src/gutil/valgrind.h | 3716 ----------------- .../http/action/check_rpc_channel_action.cpp | 4 +- be/src/http/action/stream_load.cpp | 6 +- be/src/http/action/stream_load_2pc.cpp | 3 +- .../action/tablets_distribution_action.cpp | 4 +- be/src/io/fs/broker_file_reader.cpp | 2 +- be/src/io/fs/broker_file_system.cpp | 12 +- be/src/io/fs/broker_file_writer.cpp | 4 +- be/src/olap/base_compaction.cpp | 5 - be/src/olap/compaction.cpp | 7 - be/src/olap/cumulative_compaction.cpp | 6 - be/src/olap/single_replica_compaction.cpp | 9 - be/src/olap/storage_engine.cpp | 1 - be/src/olap/tablet.cpp | 6 - be/src/olap/tablet_manager.cpp | 3 - be/src/runtime/broker_mgr.cpp | 2 +- be/src/runtime/thread_context.h | 7 +- be/src/util/cidr.cpp | 2 +- be/src/util/hash_util.hpp | 7 + be/src/util/trace.h | 31 - .../aggregate_function_java_udaf.h | 20 +- be/src/vec/runtime/vdata_stream_recvr.cpp | 2 +- be/test/CMakeLists.txt | 1 - be/test/util/trace_test.cpp | 130 - dist/LICENSE-dist.txt | 40 - 39 files changed, 75 insertions(+), 7305 deletions(-) delete mode 100644 be/src/gutil/linux_syscall_support.h delete mode 100644 be/src/gutil/spinlock_internal.cc delete mode 100644 be/src/gutil/spinlock_internal.h delete mode 100644 be/src/gutil/spinlock_linux-inl.h delete mode 100644 be/src/gutil/spinlock_posix-inl.h delete mode 100644 be/src/gutil/spinlock_win32-inl.h delete mode 100644 be/src/gutil/valgrind.h delete mode 100644 be/test/util/trace_test.cpp diff --git a/LICENSE.txt b/LICENSE.txt index 2d3871fcb6..63c614cda4 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -251,46 +251,6 @@ be/src/gutil/utf/*: licensed under the following terms: -------------------------------------------------------------------------------- -be/src/gutil/valgrind.h: licensed under the following terms: - - This file is part of Valgrind, a dynamic binary instrumentation - framework. - - Copyright (C) 2000-2008 Julian Seward. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --------------------------------------------------------------------------------- - be/src/gutil: 3-clause BSD Except above files in this module, other files of this module are derived from code in diff --git a/be/CMakeLists.txt b/be/CMakeLists.txt index 712f11f672..fde8fc9016 100644 --- a/be/CMakeLists.txt +++ b/be/CMakeLists.txt @@ -509,8 +509,7 @@ add_compile_options(-g $<$:-Wnon-virtual-dtor>) add_compile_options(-Wno-unused-parameter - -Wno-sign-compare - -Wno-array-bounds) + -Wno-sign-compare) if (COMPILER_GCC) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "11.1") @@ -530,14 +529,14 @@ if (COMPILER_CLANG) add_compile_options(-fcolor-diagnostics -Wpedantic + -Wunused + -Wunused-command-line-argument + -Wunused-exception-parameter + -Wunused-volatile-lvalue -Wunused-template - -Wunused-private-field - -Wunused-property-ivar -Wunused-member-function -Wunused-macros) - add_compile_options(-Wno-variadic-macros - -Wno-gnu-zero-variadic-macro-arguments - -Wno-vla-extension) + add_compile_options(-Wno-vla-extension) if (USE_LIBCPP) add_compile_options($<$:-stdlib=libc++>) if (NOT OS_MACOSX) diff --git a/be/src/agent/task_worker_pool.cpp b/be/src/agent/task_worker_pool.cpp index c3ec02f08d..493d666fcd 100644 --- a/be/src/agent/task_worker_pool.cpp +++ b/be/src/agent/task_worker_pool.cpp @@ -297,7 +297,6 @@ void TaskWorkerPool::_remove_task_info(const TTaskType::type task_type, int64_t VLOG_NOTICE << "remove task info. type=" << task_type << ", signature=" << signature << ", queue_size=" << queue_size; - TRACE("remove task info"); } void TaskWorkerPool::_finish_task(const TFinishTaskRequest& finish_task_request) { @@ -322,7 +321,6 @@ void TaskWorkerPool::_finish_task(const TFinishTaskRequest& finish_task_request) } sleep(config::sleep_one_second); } - TRACE("finish task"); } void TaskWorkerPool::_alter_inverted_index_worker_thread_callback() { @@ -1209,7 +1207,8 @@ void CreateTableTaskPool::_create_tablet_worker_thread_callback() { }); ADOPT_TRACE(trace.get()); DorisMetrics::instance()->create_tablet_requests_total->increment(1); - TRACE("start to create tablet $0", create_tablet_req.tablet_id); + VLOG_NOTICE << "start to create tablet " << create_tablet_req.tablet_id; + std::vector finish_tablet_infos; VLOG_NOTICE << "create tablet: " << create_tablet_req; Status status = _env->storage_engine()->create_tablet(create_tablet_req); diff --git a/be/src/agent/user_resource_listener.cpp b/be/src/agent/user_resource_listener.cpp index 07ae1ee6b0..95851549a4 100644 --- a/be/src/agent/user_resource_listener.cpp +++ b/be/src/agent/user_resource_listener.cpp @@ -86,10 +86,11 @@ void UserResourceListener::update_users_resource(int64_t new_version) { if (!master_status.ok()) { LOG(WARNING) << "Reopen to get frontend client failed, with address:" << _master_info.network_address.hostname << ":" - << _master_info.network_address.port; + << _master_info.network_address.port << ", reason=" << e.what(); return; } - LOG(WARNING) << "fetchResource from frontend failed, retry!"; + LOG(WARNING) << "fetchResource from frontend failed" + << ", reason=" << e.what(); client->fetchResource(new_fetched_resource); } } catch (TException& e) { diff --git a/be/src/common/logging.h b/be/src/common/logging.h index 894db39cda..268e803fc2 100644 --- a/be/src/common/logging.h +++ b/be/src/common/logging.h @@ -17,6 +17,8 @@ #pragma once +#include + // GLOG defines this based on the system but doesn't check if it's already // been defined. undef it first to avoid warnings. // glog MUST be included before gflags. Instead of including them, @@ -70,43 +72,45 @@ bool init_glog(const char* basename); // flushed. May only be called once. void shutdown_logging(); -/// Wrap a glog stream and tag on the log. usage: -/// LOG_INFO("here is an info for a {} query", query_type).tag("query_id", queryId); -#define LOG_INFO(...) doris::TaggableLogger(LOG(INFO), ##__VA_ARGS__) -#define LOG_WARNING(...) doris::TaggableLogger(LOG(WARNING), ##__VA_ARGS__) -#define LOG_ERROR(...) doris::TaggableLogger(LOG(ERROR), ##__VA_ARGS__) -#define LOG_FATAL(...) doris::TaggableLogger(LOG(FATAL), ##__VA_ARGS__) - class TaggableLogger { public: + TaggableLogger(const char* file, int line, google::LogSeverity severity) + : _msg(file, line, severity) {} + template - TaggableLogger(std::ostream& stream, std::string_view fmt, Args&&... args) : _stream(stream) { + TaggableLogger& operator()(const std::string_view& fmt, Args&&... args) { if constexpr (sizeof...(args) == 0) { - _stream << fmt; + _msg.stream() << fmt; } else { - _stream << fmt::format(fmt, std::forward(args)...); + _msg.stream() << fmt::format(fmt, std::forward(args)...); } + return *this; } template - TaggableLogger& tag(std::string_view key, const V& value) { - _stream << '|' << key << '='; + TaggableLogger& tag(std::string_view key, V&& value) { + _msg.stream() << '|' << key << '='; if constexpr (std::is_same_v || std::is_same_v) { - _stream << print_id(value); + _msg.stream() << print_id(value); } else { - _stream << value; + _msg.stream() << value; } return *this; } template - TaggableLogger& error(const E& error) { - _stream << "|error=" << error; + TaggableLogger& error(E&& error) { + _msg.stream() << "|error=" << error; return *this; } private: - std::ostream& _stream; + google::LogMessage _msg; }; +#define LOG_INFO TaggableLogger(__FILE__, __LINE__, google::GLOG_INFO) +#define LOG_WARNING TaggableLogger(__FILE__, __LINE__, google::GLOG_WARNING) +#define LOG_ERROR TaggableLogger(__FILE__, __LINE__, google::GLOG_ERROR) +#define LOG_FATAL TaggableLogger(__FILE__, __LINE__, google::GLOG_FATAL) + } // namespace doris diff --git a/be/src/gutil/CMakeLists.txt b/be/src/gutil/CMakeLists.txt index 4782932ef8..bac9aec303 100644 --- a/be/src/gutil/CMakeLists.txt +++ b/be/src/gutil/CMakeLists.txt @@ -31,7 +31,6 @@ SET(SOURCE_FILES hash/jenkins.cc int128.cc ref_counted.cc - spinlock_internal.cc stringprintf.cc strings/ascii_ctype.cc strings/charset.cc diff --git a/be/src/gutil/dynamic_annotations.c b/be/src/gutil/dynamic_annotations.c index 32c032b2a5..4a4ef56e46 100644 --- a/be/src/gutil/dynamic_annotations.c +++ b/be/src/gutil/dynamic_annotations.c @@ -40,11 +40,6 @@ #include "gutil/dynamic_annotations.h" -#ifdef __GNUC__ -/* valgrind.h uses gcc extensions so it won't build with other compilers */ -#include "gutil/valgrind.h" -#endif - /* Compiler-based ThreadSanitizer defines DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1 and provides its own definitions of the functions. */ @@ -131,43 +126,4 @@ void AnnotateFlushState(const char *file, int line){} #if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 -static int GetRunningOnValgrind(void) { -#ifdef RUNNING_ON_VALGRIND - if (RUNNING_ON_VALGRIND) return 1; -#endif - char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND"); - if (running_on_valgrind_str) { - return strcmp(running_on_valgrind_str, "0") != 0; - } - return 0; -} - -/* See the comments in dynamic_annotations.h */ -int RunningOnValgrind(void) { - static volatile int running_on_valgrind = -1; - int local_running_on_valgrind = running_on_valgrind; - /* C doesn't have thread-safe initialization of statics, and we - don't want to depend on pthread_once here, so hack it. */ - ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack"); - if (local_running_on_valgrind == -1) - running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind(); - return local_running_on_valgrind; -} - -/* See the comments in dynamic_annotations.h */ -double ValgrindSlowdown(void) { - /* Same initialization hack as in RunningOnValgrind(). */ - static volatile double slowdown = 0.0; - double local_slowdown = slowdown; - ANNOTATE_BENIGN_RACE(&slowdown, "safe hack"); - if (RunningOnValgrind() == 0) { - return 1.0; - } - if (local_slowdown == 0.0) { - char *env = getenv("VALGRIND_SLOWDOWN"); - slowdown = local_slowdown = env ? atof(env) : 50.0; - } - return local_slowdown; -} - #endif /* DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */ diff --git a/be/src/gutil/dynamic_annotations.h b/be/src/gutil/dynamic_annotations.h index 0001eef160..b1ded1c583 100644 --- a/be/src/gutil/dynamic_annotations.h +++ b/be/src/gutil/dynamic_annotations.h @@ -482,36 +482,6 @@ void AnnotateEnableRaceDetection(const char* file, int line, int enable); void AnnotateNoOp(const char* file, int line, const volatile void* arg); void AnnotateFlushState(const char* file, int line); -/* Return non-zero value if running under valgrind. - - If "valgrind.h" is included into dynamic_annotations.c, - the regular valgrind mechanism will be used. - See http://valgrind.org/docs/manual/manual-core-adv.html about - RUNNING_ON_VALGRIND and other valgrind "client requests". - The file "valgrind.h" may be obtained by doing - svn co svn://svn.valgrind.org/valgrind/trunk/include - - If for some reason you can't use "valgrind.h" or want to fake valgrind, - there are two ways to make this function return non-zero: - - Use environment variable: export RUNNING_ON_VALGRIND=1 - - Make your tool intercept the function RunningOnValgrind() and - change its return value. - */ -int RunningOnValgrind(void); - -/* ValgrindSlowdown returns: - * 1.0, if (RunningOnValgrind() == 0) - * 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") == NULL) - * atof(getenv("VALGRIND_SLOWDOWN")) otherwise - This function can be used to scale timeout values: - EXAMPLE: - for (;;) { - DoExpensiveBackgroundTask(); - SleepForSeconds(5 * ValgrindSlowdown()); - } - */ -double ValgrindSlowdown(void); - /* AddressSanitizer annotations from LLVM asan_interface.h */ #if defined(__SANITIZE_ADDRESS__) || defined(ADDRESS_SANITIZER) diff --git a/be/src/gutil/linux_syscall_support.h b/be/src/gutil/linux_syscall_support.h deleted file mode 100644 index 78d9ff62ba..0000000000 --- a/be/src/gutil/linux_syscall_support.h +++ /dev/null @@ -1,2777 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- -/* Copyright (c) 2005-2008, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * --- - * Author: Markus Gutschke - */ - -/* This file includes Linux-specific support functions common to the - * coredumper and the thread lister; primarily, this is a collection - * of direct system calls, and a couple of symbols missing from - * standard header files. - * There are a few options that the including file can set to control - * the behavior of this file: - * - * SYS_CPLUSPLUS: - * The entire header file will normally be wrapped in 'extern "C" { }", - * making it suitable for compilation as both C and C++ source. If you - * do not want to do this, you can set the SYS_CPLUSPLUS macro to inhibit - * the wrapping. N.B. doing so will suppress inclusion of all prerequisite - * system header files, too. It is the caller's responsibility to provide - * the necessary definitions. - * - * SYS_ERRNO: - * All system calls will update "errno" unless overridden by setting the - * SYS_ERRNO macro prior to including this file. SYS_ERRNO should be - * an l-value. - * - * SYS_INLINE: - * New symbols will be defined "static inline", unless overridden by - * the SYS_INLINE macro. - * - * SYS_LINUX_SYSCALL_SUPPORT_H - * This macro is used to avoid multiple inclusions of this header file. - * If you need to include this file more than once, make sure to - * unset SYS_LINUX_SYSCALL_SUPPORT_H before each inclusion. - * - * SYS_PREFIX: - * New system calls will have a prefix of "sys_" unless overridden by - * the SYS_PREFIX macro. Valid values for this macro are [0..9] which - * results in prefixes "sys[0..9]_". It is also possible to set this - * macro to -1, which avoids all prefixes. - * - * This file defines a few internal symbols that all start with "LSS_". - * Do not access these symbols from outside this file. They are not part - * of the supported API. - * - * NOTE: This is a stripped down version of the official opensource - * version of linux_syscall_support.h, which lives at - * http://code.google.com/p/linux-syscall-support/ - * It includes only the syscalls that are used in perftools, plus a - * few extra. Here's the breakdown: - * 1) Perftools uses these: grep -rho 'sys_[a-z0-9_A-Z]* *(' src | sort -u - * sys__exit( - * sys_clone( - * sys_close( - * sys_fcntl( - * sys_fstat( - * sys_futex( - * sys_getcpu( - * sys_getdents64( - * sys_getppid( - * sys_gettid( - * sys_lseek( - * sys_mmap( - * sys_mremap( - * sys_munmap( - * sys_open( - * sys_pipe( - * sys_prctl( - * sys_ptrace( - * sys_ptrace_detach( - * sys_read( - * sys_sched_yield( - * sys_sigaction( - * sys_sigaltstack( - * sys_sigdelset( - * sys_sigfillset( - * sys_sigprocmask( - * sys_socket( - * sys_stat( - * sys_waitpid( - * 2) These are used as subroutines of the above: - * sys_getpid -- gettid - * sys_kill -- ptrace_detach - * sys_restore -- sigaction - * sys_restore_rt -- sigaction - * sys_socketcall -- socket - * sys_wait4 -- waitpid - * 3) I left these in even though they're not used. They either - * complement the above (write vs read) or are variants (rt_sigaction): - * sys_fstat64 - * sys_llseek - * sys_mmap2 - * sys_openat - * sys_getdents - * sys_rt_sigaction - * sys_rt_sigprocmask - * sys_sigaddset - * sys_sigemptyset - * sys_stat64 - * sys_write - */ -#ifndef SYS_LINUX_SYSCALL_SUPPORT_H -#define SYS_LINUX_SYSCALL_SUPPORT_H - -/* We currently only support x86-32, x86-64, ARM, MIPS, PPC/PPC64, Aarch64, s390 and s390x - * on Linux. - * Porting to other related platforms should not be difficult. - */ -#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \ - defined(__PPC__) || defined(__aarch64__) || defined(__s390__)) && \ - (defined(__linux)) - -#ifndef SYS_CPLUSPLUS -#ifdef __cplusplus -/* Some system header files in older versions of gcc neglect to properly - * handle being included from C++. As it appears to be harmless to have - * multiple nested 'extern "C"' blocks, just add another one here. - */ -extern "C" { -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __mips__ -/* Include definitions of the ABI currently in use. */ -#include -#endif - -#endif - -/* As glibc often provides subtly incompatible data structures (and implicit - * wrapper functions that convert them), we provide our own kernel data - * structures for use by the system calls. - * These structures have been developed by using Linux 2.6.23 headers for - * reference. Note though, we do not care about exact API compatibility - * with the kernel, and in fact the kernel often does not have a single - * API that works across architectures. Instead, we try to mimic the glibc - * API where reasonable, and only guarantee ABI compatibility with the - * kernel headers. - * Most notably, here are a few changes that were made to the structures - * defined by kernel headers: - * - * - we only define structures, but not symbolic names for kernel data - * types. For the latter, we directly use the native C datatype - * (i.e. "unsigned" instead of "mode_t"). - * - in a few cases, it is possible to define identical structures for - * both 32bit (e.g. i386) and 64bit (e.g. x86-64) platforms by - * standardizing on the 64bit version of the data types. In particular, - * this means that we use "unsigned" where the 32bit headers say - * "unsigned long". - * - overall, we try to minimize the number of cases where we need to - * conditionally define different structures. - * - the "struct kernel_sigaction" class of structures have been - * modified to more closely mimic glibc's API by introducing an - * anonymous union for the function pointer. - * - a small number of field names had to have an underscore appended to - * them, because glibc defines a global macro by the same name. - */ - -/* include/linux/dirent.h */ -struct kernel_dirent64 { - unsigned long long d_ino; - long long d_off; - unsigned short d_reclen; - unsigned char d_type; - char d_name[256]; -}; - -/* include/linux/dirent.h */ -struct kernel_dirent { - long d_ino; - long d_off; - unsigned short d_reclen; - char d_name[256]; -}; - -/* include/linux/time.h */ -struct kernel_timespec { - long tv_sec; - long tv_nsec; -}; - -/* include/linux/time.h */ -struct kernel_timeval { - long tv_sec; - long tv_usec; -}; - -/* include/linux/resource.h */ -struct kernel_rusage { - struct kernel_timeval ru_utime; - struct kernel_timeval ru_stime; - long ru_maxrss; - long ru_ixrss; - long ru_idrss; - long ru_isrss; - long ru_minflt; - long ru_majflt; - long ru_nswap; - long ru_inblock; - long ru_oublock; - long ru_msgsnd; - long ru_msgrcv; - long ru_nsignals; - long ru_nvcsw; - long ru_nivcsw; -}; - -#if defined(__i386__) || defined(__arm__) || defined(__PPC__) || \ - (defined(__s390__) && !defined(__s390x__)) - -/* include/asm-{arm,i386,mips,ppc}/signal.h */ -struct kernel_old_sigaction { - union { - void (*sa_handler_)(int); - void (*sa_sigaction_)(int, siginfo_t*, void*); - }; - unsigned long sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -} __attribute__((packed, aligned(4))); -#elif (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) -#define kernel_old_sigaction kernel_sigaction -#elif defined(__aarch64__) -// No kernel_old_sigaction defined for arm64. -#endif - -/* Some kernel functions (e.g. sigaction() in 2.6.23) require that the - * exactly match the size of the signal set, even though the API was - * intended to be extensible. We define our own KERNEL_NSIG to deal with - * this. - * Please note that glibc provides signals [1.._NSIG-1], whereas the - * kernel (and this header) provides the range [1..KERNEL_NSIG]. The - * actual number of signals is obviously the same, but the constants - * differ by one. - */ -#ifdef __mips__ -#define KERNEL_NSIG 128 -#else -#define KERNEL_NSIG 64 -#endif - -/* include/asm-{arm,i386,mips,x86_64}/signal.h */ -struct kernel_sigset_t { - unsigned long sig[(KERNEL_NSIG + 8 * sizeof(unsigned long) - 1) / (8 * sizeof(unsigned long))]; -}; - -/* include/asm-{arm,generic,i386,mips,x86_64,ppc}/signal.h */ -struct kernel_sigaction { -#ifdef __mips__ - unsigned long sa_flags; - union { - void (*sa_handler_)(int); - void (*sa_sigaction_)(int, siginfo_t*, void*); - }; - struct kernel_sigset_t sa_mask; -#else - union { - void (*sa_handler_)(int); - void (*sa_sigaction_)(int, siginfo_t*, void*); - }; - unsigned long sa_flags; - void (*sa_restorer)(void); - struct kernel_sigset_t sa_mask; -#endif -}; - -/* include/asm-{arm,i386,mips,ppc,s390}/stat.h */ -#ifdef __mips__ -#if (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32) -struct kernel_stat { -#else -struct kernel_stat64 { -#endif - unsigned st_dev; - unsigned __pad0[3]; - unsigned long long st_ino; - unsigned st_mode; - unsigned st_nlink; - unsigned st_uid; - unsigned st_gid; - unsigned st_rdev; - unsigned __pad1[3]; - long long st_size; - unsigned st_atime_; - unsigned st_atime_nsec_; - unsigned st_mtime_; - unsigned st_mtime_nsec_; - unsigned st_ctime_; - unsigned st_ctime_nsec_; - unsigned st_blksize; - unsigned __pad2; - unsigned long long st_blocks; -}; -#elif defined __PPC__ -struct kernel_stat64 { - unsigned long long st_dev; - unsigned long long st_ino; - unsigned st_nlink; - unsigned st_mode; - unsigned st_uid; - unsigned st_gid; - int __pad2; - unsigned long long st_rdev; - long long st_size; - long long st_blksize; - long long st_blocks; - kernel_timespec st_atim; - kernel_timespec st_mtim; - kernel_timespec st_ctim; - unsigned long __unused4; - unsigned long __unused5; - unsigned long __unused6; -}; -#else -struct kernel_stat64 { - unsigned long long st_dev; - unsigned char __pad0[4]; - unsigned __st_ino; - unsigned st_mode; - unsigned st_nlink; - unsigned st_uid; - unsigned st_gid; - unsigned long long st_rdev; - unsigned char __pad3[4]; - long long st_size; - unsigned st_blksize; - unsigned long long st_blocks; - unsigned st_atime_; - unsigned st_atime_nsec_; - unsigned st_mtime_; - unsigned st_mtime_nsec_; - unsigned st_ctime_; - unsigned st_ctime_nsec_; - unsigned long long st_ino; -}; -#endif - -/* include/asm-{arm,generic,i386,mips,x86_64,ppc,s390}/stat.h */ -#if defined(__i386__) || defined(__arm__) -struct kernel_stat { - /* The kernel headers suggest that st_dev and st_rdev should be 32bit - * quantities encoding 12bit major and 20bit minor numbers in an interleaved - * format. In reality, we do not see useful data in the top bits. So, - * we'll leave the padding in here, until we find a better solution. - */ - unsigned short st_dev; - short pad1; - unsigned st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - unsigned short st_rdev; - short pad2; - unsigned st_size; - unsigned st_blksize; - unsigned st_blocks; - unsigned st_atime_; - unsigned st_atime_nsec_; - unsigned st_mtime_; - unsigned st_mtime_nsec_; - unsigned st_ctime_; - unsigned st_ctime_nsec_; - unsigned __unused4; - unsigned __unused5; -}; -#elif defined(__x86_64__) -struct kernel_stat { - uint64_t st_dev; - uint64_t st_ino; - uint64_t st_nlink; - unsigned st_mode; - unsigned st_uid; - unsigned st_gid; - unsigned __pad0; - uint64_t st_rdev; - int64_t st_size; - int64_t st_blksize; - int64_t st_blocks; - uint64_t st_atime_; - uint64_t st_atime_nsec_; - uint64_t st_mtime_; - uint64_t st_mtime_nsec_; - uint64_t st_ctime_; - uint64_t st_ctime_nsec_; - int64_t __unused[3]; -}; -#elif defined(__PPC__) -struct kernel_stat { - unsigned long long st_dev; - unsigned long st_ino; - unsigned long st_nlink; - unsigned long st_mode; - unsigned st_uid; - unsigned st_gid; - int __pad2; - unsigned long long st_rdev; - long st_size; - unsigned long st_blksize; - unsigned long st_blocks; - kernel_timespec st_atim; - kernel_timespec st_mtim; - kernel_timespec st_ctim; - unsigned long __unused4; - unsigned long __unused5; - unsigned long __unused6; -}; -#elif defined(__mips__) && !(_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32) -struct kernel_stat { - unsigned st_dev; - int st_pad1[3]; - unsigned st_ino; - unsigned st_mode; - unsigned st_nlink; - unsigned st_uid; - unsigned st_gid; - unsigned st_rdev; - int st_pad2[2]; - long st_size; - int st_pad3; - long st_atime_; - long st_atime_nsec_; - long st_mtime_; - long st_mtime_nsec_; - long st_ctime_; - long st_ctime_nsec_; - int st_blksize; - int st_blocks; - int st_pad4[14]; -}; -#elif defined(__aarch64__) -struct kernel_stat { - unsigned long st_dev; - unsigned long st_ino; - unsigned int st_mode; - unsigned int st_nlink; - unsigned int st_uid; - unsigned int st_gid; - unsigned long st_rdev; - unsigned long __pad1; - long st_size; - int st_blksize; - int __pad2; - long st_blocks; - long st_atime_; - unsigned long st_atime_nsec_; - long st_mtime_; - unsigned long st_mtime_nsec_; - long st_ctime_; - unsigned long st_ctime_nsec_; - unsigned int __unused4; - unsigned int __unused5; -}; -#elif defined(__s390x__) -struct kernel_stat { - unsigned long st_dev; - unsigned long st_ino; - unsigned long st_nlink; - unsigned int st_mode; - unsigned int st_uid; - unsigned int st_gid; - unsigned int __pad1; - unsigned long st_rdev; - unsigned long st_size; - unsigned long st_atime_; - unsigned long st_atime_nsec_; - unsigned long st_mtime_; - unsigned long st_mtime_nsec_; - unsigned long st_ctime_; - unsigned long st_ctime_nsec_; - unsigned long st_blksize; - long st_blocks; - unsigned long __unused[3]; -}; -#elif defined(__s390__) -struct kernel_stat { - unsigned short st_dev; - unsigned short __pad1; - unsigned long st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - unsigned short st_rdev; - unsigned short __pad2; - unsigned long st_size; - unsigned long st_blksize; - unsigned long st_blocks; - unsigned long st_atime_; - unsigned long st_atime_nsec_; - unsigned long st_mtime_; - unsigned long st_mtime_nsec_; - unsigned long st_ctime_; - unsigned long st_ctime_nsec_; - unsigned long __unused4; - unsigned long __unused5; -}; -#endif - -/* Definitions missing from the standard header files */ -#ifndef O_DIRECTORY -#if defined(__arm__) -#define O_DIRECTORY 0040000 -#else -#define O_DIRECTORY 0200000 -#endif -#endif -#ifndef PR_GET_DUMPABLE -#define PR_GET_DUMPABLE 3 -#endif -#ifndef PR_SET_DUMPABLE -#define PR_SET_DUMPABLE 4 -#endif -#ifndef AT_FDCWD -#define AT_FDCWD (-100) -#endif -#ifndef AT_SYMLINK_NOFOLLOW -#define AT_SYMLINK_NOFOLLOW 0x100 -#endif -#ifndef AT_REMOVEDIR -#define AT_REMOVEDIR 0x200 -#endif -#ifndef MREMAP_FIXED -#define MREMAP_FIXED 2 -#endif -#ifndef SA_RESTORER -#define SA_RESTORER 0x04000000 -#endif - -#if defined(__i386__) -#ifndef __NR_rt_sigaction -#define __NR_rt_sigaction 174 -#define __NR_rt_sigprocmask 175 -#endif -#ifndef __NR_stat64 -#define __NR_stat64 195 -#endif -#ifndef __NR_fstat64 -#define __NR_fstat64 197 -#endif -#ifndef __NR_getdents64 -#define __NR_getdents64 220 -#endif -#ifndef __NR_gettid -#define __NR_gettid 224 -#endif -#ifndef __NR_futex -#define __NR_futex 240 -#endif -#ifndef __NR_openat -#define __NR_openat 295 -#endif -#ifndef __NR_getcpu -#define __NR_getcpu 318 -#endif -/* End of i386 definitions */ -#elif defined(__arm__) -#ifndef __syscall -#if defined(__thumb__) || defined(__ARM_EABI__) -#define __SYS_REG(name) register long __sysreg __asm__("r6") = __NR_##name; -#define __SYS_REG_LIST(regs...) [sysreg] "r"(__sysreg), ##regs -#define __syscall(name) "swi\t0" -#define __syscall_safe(name) \ - "push {r7}\n" \ - "mov r7,%[sysreg]\n" \ - __syscall(name)"\n" \ - "pop {r7}" -#else -#define __SYS_REG(name) -#define __SYS_REG_LIST(regs...) regs -#define __syscall(name) "swi\t" __sys1(__NR_##name) "" -#define __syscall_safe(name) __syscall(name) -#endif -#endif -#ifndef __NR_rt_sigaction -#define __NR_rt_sigaction (__NR_SYSCALL_BASE + 174) -#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE + 175) -#endif -#ifndef __NR_stat64 -#define __NR_stat64 (__NR_SYSCALL_BASE + 195) -#endif -#ifndef __NR_fstat64 -#define __NR_fstat64 (__NR_SYSCALL_BASE + 197) -#endif -#ifndef __NR_getdents64 -#define __NR_getdents64 (__NR_SYSCALL_BASE + 217) -#endif -#ifndef __NR_gettid -#define __NR_gettid (__NR_SYSCALL_BASE + 224) -#endif -#ifndef __NR_futex -#define __NR_futex (__NR_SYSCALL_BASE + 240) -#endif -/* End of ARM definitions */ -#elif defined(__x86_64__) -#ifndef __NR_gettid -#define __NR_gettid 186 -#endif -#ifndef __NR_futex -#define __NR_futex 202 -#endif -#ifndef __NR_getdents64 -#define __NR_getdents64 217 -#endif -#ifndef __NR_openat -#define __NR_openat 257 -#endif -/* End of x86-64 definitions */ -#elif defined(__mips__) -#if _MIPS_SIM == _MIPS_SIM_ABI32 -#ifndef __NR_rt_sigaction -#define __NR_rt_sigaction (__NR_Linux + 194) -#define __NR_rt_sigprocmask (__NR_Linux + 195) -#endif -#ifndef __NR_stat64 -#define __NR_stat64 (__NR_Linux + 213) -#endif -#ifndef __NR_fstat64 -#define __NR_fstat64 (__NR_Linux + 215) -#endif -#ifndef __NR_getdents64 -#define __NR_getdents64 (__NR_Linux + 219) -#endif -#ifndef __NR_gettid -#define __NR_gettid (__NR_Linux + 222) -#endif -#ifndef __NR_futex -#define __NR_futex (__NR_Linux + 238) -#endif -#ifndef __NR_openat -#define __NR_openat (__NR_Linux + 288) -#endif -#ifndef __NR_fstatat -#define __NR_fstatat (__NR_Linux + 293) -#endif -#ifndef __NR_getcpu -#define __NR_getcpu (__NR_Linux + 312) -#endif -/* End of MIPS (old 32bit API) definitions */ -#elif (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32) -#ifndef __NR_gettid -#define __NR_gettid (__NR_Linux + 178) -#endif -#ifndef __NR_futex -#define __NR_futex (__NR_Linux + 194) -#endif -#ifndef __NR_openat -#define __NR_openat (__NR_Linux + 247) -#endif -#ifndef __NR_fstatat -#define __NR_fstatat (__NR_Linux + 252) -#endif -#ifndef __NR_getcpu -#define __NR_getcpu (__NR_Linux + 271) -#endif -/* End of MIPS (64bit API) definitions */ -#else -#ifndef __NR_gettid -#define __NR_gettid (__NR_Linux + 178) -#endif -#ifndef __NR_futex -#define __NR_futex (__NR_Linux + 194) -#endif -#ifndef __NR_openat -#define __NR_openat (__NR_Linux + 251) -#endif -#ifndef __NR_fstatat -#define __NR_fstatat (__NR_Linux + 256) -#endif -#ifndef __NR_getcpu -#define __NR_getcpu (__NR_Linux + 275) -#endif -/* End of MIPS (new 32bit API) definitions */ -#endif -/* End of MIPS definitions */ -#elif defined(__PPC__) -#ifndef __NR_rt_sigaction -#define __NR_rt_sigaction 173 -#define __NR_rt_sigprocmask 174 -#endif -#ifndef __NR_stat64 -#define __NR_stat64 195 -#endif -#ifndef __NR_fstat64 -#define __NR_fstat64 197 -#endif -#ifndef __NR_socket -#define __NR_socket 198 -#endif -#ifndef __NR_getdents64 -#define __NR_getdents64 202 -#endif -#ifndef __NR_gettid -#define __NR_gettid 207 -#endif -#ifndef __NR_futex -#define __NR_futex 221 -#endif -#ifndef __NR_openat -#define __NR_openat 286 -#endif -#ifndef __NR_getcpu -#define __NR_getcpu 302 -#endif -/* End of powerpc defininitions */ -#elif defined(__aarch64__) -#ifndef __NR_fstatat -#define __NR_fstatat 79 -#endif -/* End of aarch64 defininitions */ -#elif defined(__s390__) -#ifndef __NR_quotactl -#define __NR_quotactl 131 -#endif -#ifndef __NR_rt_sigreturn -#define __NR_rt_sigreturn 173 -#endif -#ifndef __NR_rt_sigaction -#define __NR_rt_sigaction 174 -#endif -#ifndef __NR_rt_sigprocmask -#define __NR_rt_sigprocmask 175 -#endif -#ifndef __NR_rt_sigpending -#define __NR_rt_sigpending 176 -#endif -#ifndef __NR_rt_sigsuspend -#define __NR_rt_sigsuspend 179 -#endif -#ifndef __NR_pread64 -#define __NR_pread64 180 -#endif -#ifndef __NR_pwrite64 -#define __NR_pwrite64 181 -#endif -#ifndef __NR_getdents64 -#define __NR_getdents64 220 -#endif -#ifndef __NR_readahead -#define __NR_readahead 222 -#endif -#ifndef __NR_setxattr -#define __NR_setxattr 224 -#endif -#ifndef __NR_lsetxattr -#define __NR_lsetxattr 225 -#endif -#ifndef __NR_getxattr -#define __NR_getxattr 227 -#endif -#ifndef __NR_lgetxattr -#define __NR_lgetxattr 228 -#endif -#ifndef __NR_listxattr -#define __NR_listxattr 230 -#endif -#ifndef __NR_llistxattr -#define __NR_llistxattr 231 -#endif -#ifndef __NR_gettid -#define __NR_gettid 236 -#endif -#ifndef __NR_tkill -#define __NR_tkill 237 -#endif -#ifndef __NR_futex -#define __NR_futex 238 -#endif -#ifndef __NR_sched_setaffinity -#define __NR_sched_setaffinity 239 -#endif -#ifndef __NR_sched_getaffinity -#define __NR_sched_getaffinity 240 -#endif -#ifndef __NR_set_tid_address -#define __NR_set_tid_address 252 -#endif -#ifndef __NR_clock_gettime -#define __NR_clock_gettime 260 -#endif -#ifndef __NR_clock_getres -#define __NR_clock_getres 261 -#endif -#ifndef __NR_statfs64 -#define __NR_statfs64 265 -#endif -#ifndef __NR_fstatfs64 -#define __NR_fstatfs64 266 -#endif -#ifndef __NR_ioprio_set -#define __NR_ioprio_set 282 -#endif -#ifndef __NR_ioprio_get -#define __NR_ioprio_get 283 -#endif -#ifndef __NR_openat -#define __NR_openat 288 -#endif -#ifndef __NR_unlinkat -#define __NR_unlinkat 294 -#endif -#ifndef __NR_move_pages -#define __NR_move_pages 310 -#endif -#ifndef __NR_getcpu -#define __NR_getcpu 311 -#endif -#ifndef __NR_fallocate -#define __NR_fallocate 314 -#endif -/* Some syscalls are named/numbered differently between s390 and s390x. */ -#ifdef __s390x__ -#ifndef __NR_getrlimit -#define __NR_getrlimit 191 -#endif -#ifndef __NR_setresuid -#define __NR_setresuid 208 -#endif -#ifndef __NR_getresuid -#define __NR_getresuid 209 -#endif -#ifndef __NR_setresgid -#define __NR_setresgid 210 -#endif -#ifndef __NR_getresgid -#define __NR_getresgid 211 -#endif -#ifndef __NR_setfsuid -#define __NR_setfsuid 215 -#endif -#ifndef __NR_setfsgid -#define __NR_setfsgid 216 -#endif -#ifndef __NR_fadvise64 -#define __NR_fadvise64 253 -#endif -#ifndef __NR_newfstatat -#define __NR_newfstatat 293 -#endif -#else /* __s390x__ */ -#ifndef __NR_getrlimit -#define __NR_getrlimit 76 -#endif -#ifndef __NR_setfsuid -#define __NR_setfsuid 138 -#endif -#ifndef __NR_setfsgid -#define __NR_setfsgid 139 -#endif -#ifndef __NR_setresuid -#define __NR_setresuid 164 -#endif -#ifndef __NR_getresuid -#define __NR_getresuid 165 -#endif -#ifndef __NR_setresgid -#define __NR_setresgid 170 -#endif -#ifndef __NR_getresgid -#define __NR_getresgid 171 -#endif -#ifndef __NR_ugetrlimit -#define __NR_ugetrlimit 191 -#endif -#ifndef __NR_mmap2 -#define __NR_mmap2 192 -#endif -#ifndef __NR_setresuid32 -#define __NR_setresuid32 208 -#endif -#ifndef __NR_getresuid32 -#define __NR_getresuid32 209 -#endif -#ifndef __NR_setresgid32 -#define __NR_setresgid32 210 -#endif -#ifndef __NR_getresgid32 -#define __NR_getresgid32 211 -#endif -#ifndef __NR_setfsuid32 -#define __NR_setfsuid32 215 -#endif -#ifndef __NR_setfsgid32 -#define __NR_setfsgid32 216 -#endif -#ifndef __NR_fadvise64_64 -#define __NR_fadvise64_64 264 -#endif -#ifndef __NR_fstatat64 -#define __NR_fstatat64 293 -#endif -#endif /* __s390__ */ -/* End of s390/s390x definitions */ -#endif - -/* After forking, we must make sure to only call system calls. */ -#if __BOUNDED_POINTERS__ -#error "Need to port invocations of syscalls for bounded ptrs" -#else -/* The core dumper and the thread lister get executed after threads - * have been suspended. As a consequence, we cannot call any functions - * that acquire locks. Unfortunately, libc wraps most system calls - * (e.g. in order to implement pthread_atfork, and to make calls - * cancellable), which means we cannot call these functions. Instead, - * we have to call syscall() directly. - */ -#undef LSS_ERRNO -#ifdef SYS_ERRNO -/* Allow the including file to override the location of errno. This can - * be useful when using clone() with the CLONE_VM option. - */ -#define LSS_ERRNO SYS_ERRNO -#else -#define LSS_ERRNO errno -#endif - -#undef LSS_INLINE -#ifdef SYS_INLINE -#define LSS_INLINE SYS_INLINE -#else -#define LSS_INLINE static inline -#endif - -/* Allow the including file to override the prefix used for all new - * system calls. By default, it will be set to "sys_". - */ -#undef LSS_NAME -#ifndef SYS_PREFIX -#define LSS_NAME(name) sys_##name -#elif SYS_PREFIX < 0 -#define LSS_NAME(name) name -#elif SYS_PREFIX == 0 -#define LSS_NAME(name) sys0_##name -#elif SYS_PREFIX == 1 -#define LSS_NAME(name) sys1_##name -#elif SYS_PREFIX == 2 -#define LSS_NAME(name) sys2_##name -#elif SYS_PREFIX == 3 -#define LSS_NAME(name) sys3_##name -#elif SYS_PREFIX == 4 -#define LSS_NAME(name) sys4_##name -#elif SYS_PREFIX == 5 -#define LSS_NAME(name) sys5_##name -#elif SYS_PREFIX == 6 -#define LSS_NAME(name) sys6_##name -#elif SYS_PREFIX == 7 -#define LSS_NAME(name) sys7_##name -#elif SYS_PREFIX == 8 -#define LSS_NAME(name) sys8_##name -#elif SYS_PREFIX == 9 -#define LSS_NAME(name) sys9_##name -#endif - -#undef LSS_RETURN -#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \ - defined(__s390__)) -/* Failing system calls return a negative result in the range of - * -1..-4095. These are "errno" values with the sign inverted. - */ -#define LSS_RETURN(type, res) \ - do { \ - if ((unsigned long)(res) >= (unsigned long)(-4095)) { \ - LSS_ERRNO = -(res); \ - res = -1; \ - } \ - return (type)(res); \ - } while (0) -#elif defined(__mips__) -/* On MIPS, failing system calls return -1, and set errno in a - * separate CPU register. - */ -#define LSS_RETURN(type, res, err) \ - do { \ - if (err) { \ - LSS_ERRNO = (res); \ - res = -1; \ - } \ - return (type)(res); \ - } while (0) -#elif defined(__PPC__) -/* On PPC, failing system calls return -1, and set errno in a - * separate CPU register. See linux/unistd.h. - */ -#define LSS_RETURN(type, res, err) \ - do { \ - if (err & 0x10000000) { \ - LSS_ERRNO = (res); \ - res = -1; \ - } \ - return (type)(res); \ - } while (0) -#endif -#if defined(__i386__) -#if defined(NO_FRAME_POINTER) && (100 * __GNUC__ + __GNUC_MINOR__ >= 404) -/* This only works for GCC-4.4 and above -- the first version to use - .cfi directives for dwarf unwind info. */ -#define CFI_ADJUST_CFA_OFFSET(adjust) ".cfi_adjust_cfa_offset " #adjust "\n" -#else -#define CFI_ADJUST_CFA_OFFSET(adjust) /**/ -#endif - -/* In PIC mode (e.g. when building shared libraries), gcc for i386 - * reserves ebx. Unfortunately, most distribution ship with implementations - * of _syscallX() which clobber ebx. - * Also, most definitions of _syscallX() neglect to mark "memory" as being - * clobbered. This causes problems with compilers, that do a better job - * at optimizing across __asm__ calls. - * So, we just have to redefine all of the _syscallX() macros. - */ -#undef LSS_BODY -#define LSS_BODY(type, args...) \ - long __res; \ - __asm__ __volatile__("push %%ebx\n" \ - CFI_ADJUST_CFA_OFFSET(4) \ - "movl %2,%%ebx\n" \ - "int $0x80\n" \ - "pop %%ebx\n" \ - CFI_ADJUST_CFA_OFFSET(-4) \ - args \ - : "esp", "memory"); \ - LSS_RETURN(type, __res) -#undef _syscall0 -#define _syscall0(type, name) \ - type LSS_NAME(name)(void) { \ - long __res; \ - __asm__ volatile("int $0x80" : "=a"(__res) : "0"(__NR_##name) : "memory"); \ - LSS_RETURN(type, __res); \ - } -#undef _syscall1 -#define _syscall1(type, name, type1, arg1) \ - type LSS_NAME(name)(type1 arg1) { \ - LSS_BODY(type, : "=a"(__res) : "0"(__NR_##name), "ri"((long)(arg1))); \ - } -#undef _syscall2 -#define _syscall2(type, name, type1, arg1, type2, arg2) \ - type LSS_NAME(name)(type1 arg1, type2 arg2) { \ - LSS_BODY(type, : "=a"(__res) : "0"(__NR_##name), "ri"((long)(arg1)), "c"((long)(arg2))); \ - } -#undef _syscall3 -#define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ - LSS_BODY(type, \ - : "=a"(__res) \ - : "0"(__NR_##name), "ri"((long)(arg1)), "c"((long)(arg2)), "d"((long)(arg3))); \ - } -#undef _syscall4 -#define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - LSS_BODY(type, \ - : "=a"(__res) \ - : "0"(__NR_##name), "ri"((long)(arg1)), "c"((long)(arg2)), "d"((long)(arg3)), \ - "S"((long)(arg4))); \ - } -#undef _syscall5 -#define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - long __res; \ - __asm__ __volatile__( \ - "push %%ebx\n" \ - "movl %2,%%ebx\n" \ - "movl %1,%%eax\n" \ - "int $0x80\n" \ - "pop %%ebx" \ - : "=a"(__res) \ - : "i"(__NR_##name), "ri"((long)(arg1)), "c"((long)(arg2)), "d"((long)(arg3)), \ - "S"((long)(arg4)), "D"((long)(arg5)) \ - : "esp", "memory"); \ - LSS_RETURN(type, __res); \ - } -#undef _syscall6 -#define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, \ - type6, arg6) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - long __res; \ - struct { \ - long __a1; \ - long __a6; \ - } __s = {(long)arg1, (long)arg6}; \ - __asm__ __volatile__( \ - "push %%ebp\n" \ - "push %%ebx\n" \ - "movl 4(%2),%%ebp\n" \ - "movl 0(%2), %%ebx\n" \ - "movl %1,%%eax\n" \ - "int $0x80\n" \ - "pop %%ebx\n" \ - "pop %%ebp" \ - : "=a"(__res) \ - : "i"(__NR_##name), "0"((long)(&__s)), "c"((long)(arg2)), "d"((long)(arg3)), \ - "S"((long)(arg4)), "D"((long)(arg5)) \ - : "esp", "memory"); \ - LSS_RETURN(type, __res); \ - } -LSS_INLINE int LSS_NAME(clone)(int (*fn)(void*), void* child_stack, int flags, void* arg, - int* parent_tidptr, void* newtls, int* child_tidptr) { - long __res; - __asm__ __volatile__(/* if (fn == NULL) - * return -EINVAL; - */ - "movl %3,%%ecx\n" - "jecxz 1f\n" - - /* if (child_stack == NULL) - * return -EINVAL; - */ - "movl %4,%%ecx\n" - "jecxz 1f\n" - - /* Set up alignment of the child stack: - * child_stack = (child_stack & ~0xF) - 20; - */ - "andl $-16,%%ecx\n" - "subl $20,%%ecx\n" - - /* Push "arg" and "fn" onto the stack that will be - * used by the child. - */ - "movl %6,%%eax\n" - "movl %%eax,4(%%ecx)\n" - "movl %3,%%eax\n" - "movl %%eax,(%%ecx)\n" - - /* %eax = syscall(%eax = __NR_clone, - * %ebx = flags, - * %ecx = child_stack, - * %edx = parent_tidptr, - * %esi = newtls, - * %edi = child_tidptr) - * Also, make sure that %ebx gets preserved as it is - * used in PIC mode. - */ - "movl %8,%%esi\n" - "movl %7,%%edx\n" - "movl %5,%%eax\n" - "movl %9,%%edi\n" - "pushl %%ebx\n" - "movl %%eax,%%ebx\n" - "movl %2,%%eax\n" - "int $0x80\n" - - /* In the parent: restore %ebx - * In the child: move "fn" into %ebx - */ - "popl %%ebx\n" - - /* if (%eax != 0) - * return %eax; - */ - "test %%eax,%%eax\n" - "jnz 1f\n" - - /* In the child, now. Terminate frame pointer chain. - */ - "movl $0,%%ebp\n" - - /* Call "fn". "arg" is already on the stack. - */ - "call *%%ebx\n" - - /* Call _exit(%ebx). Unfortunately older versions - * of gcc restrict the number of arguments that can - * be passed to asm(). So, we need to hard-code the - * system call number. - */ - "movl %%eax,%%ebx\n" - "movl $1,%%eax\n" - "int $0x80\n" - - /* Return to parent. - */ - "1:\n" - : "=a"(__res) - : "0"(-EINVAL), "i"(__NR_clone), "m"(fn), "m"(child_stack), "m"(flags), - "m"(arg), "m"(parent_tidptr), "m"(newtls), "m"(child_tidptr) - : "esp", "memory", "ecx", "edx", "esi", "edi"); - LSS_RETURN(int, __res); -} - -LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) { - /* On i386, the kernel does not know how to return from a signal - * handler. Instead, it relies on user space to provide a - * restorer function that calls the {rt_,}sigreturn() system call. - * Unfortunately, we cannot just reference the glibc version of this - * function, as glibc goes out of its way to make it inaccessible. - */ - void (*res)(void); - __asm__ __volatile__( - "call 2f\n" - "0:.align 16\n" - "1:movl %1,%%eax\n" - "int $0x80\n" - "2:popl %0\n" - "addl $(1b-0b),%0\n" - : "=a"(res) - : "i"(__NR_rt_sigreturn)); - return res; -} -LSS_INLINE void (*LSS_NAME(restore)(void))(void) { - /* On i386, the kernel does not know how to return from a signal - * handler. Instead, it relies on user space to provide a - * restorer function that calls the {rt_,}sigreturn() system call. - * Unfortunately, we cannot just reference the glibc version of this - * function, as glibc goes out of its way to make it inaccessible. - */ - void (*res)(void); - __asm__ __volatile__( - "call 2f\n" - "0:.align 16\n" - "1:pop %%eax\n" - "movl %1,%%eax\n" - "int $0x80\n" - "2:popl %0\n" - "addl $(1b-0b),%0\n" - : "=a"(res) - : "i"(__NR_sigreturn)); - return res; -} -#elif defined(__x86_64__) -/* There are no known problems with any of the _syscallX() macros - * currently shipping for x86_64, but we still need to be able to define - * our own version so that we can override the location of the errno - * location (e.g. when using the clone() system call with the CLONE_VM - * option). - */ -#undef LSS_ENTRYPOINT -#define LSS_ENTRYPOINT "syscall\n" - -/* The x32 ABI has 32 bit longs, but the syscall interface is 64 bit. - * We need to explicitly cast to an unsigned 64 bit type to avoid implicit - * sign extension. We can't cast pointers directly because those are - * 32 bits, and gcc will dump ugly warnings about casting from a pointer - * to an integer of a different size. - */ -#undef LSS_SYSCALL_ARG -#define LSS_SYSCALL_ARG(a) ((uint64_t)(uintptr_t)(a)) -#undef _LSS_RETURN -#define _LSS_RETURN(type, res, cast) \ - do { \ - if ((uint64_t)(res) >= (uint64_t)(-4095)) { \ - LSS_ERRNO = -(res); \ - res = -1; \ - } \ - return (type)(cast)(res); \ - } while (0) -#undef LSS_RETURN -#define LSS_RETURN(type, res) _LSS_RETURN(type, res, uintptr_t) - -#undef _LSS_BODY -#define _LSS_BODY(nr, type, name, cast, ...) \ - long long __res; \ - __asm__ __volatile__(LSS_BODY_ASM##nr LSS_ENTRYPOINT \ - : "=a"(__res) \ - : "0"(__NR_##name)LSS_BODY_ARG##nr(__VA_ARGS__) \ - : LSS_BODY_CLOBBER##nr "r11", "rcx", "memory"); \ - _LSS_RETURN(type, __res, cast) -#undef LSS_BODY -#define LSS_BODY(nr, type, name, args...) _LSS_BODY(nr, type, name, uintptr_t, ##args) - -#undef LSS_BODY_ASM0 -#undef LSS_BODY_ASM1 -#undef LSS_BODY_ASM2 -#undef LSS_BODY_ASM3 -#undef LSS_BODY_ASM4 -#undef LSS_BODY_ASM5 -#undef LSS_BODY_ASM6 -#define LSS_BODY_ASM0 -#define LSS_BODY_ASM1 LSS_BODY_ASM0 -#define LSS_BODY_ASM2 LSS_BODY_ASM1 -#define LSS_BODY_ASM3 LSS_BODY_ASM2 -#define LSS_BODY_ASM4 LSS_BODY_ASM3 "movq %5,%%r10;" -#define LSS_BODY_ASM5 LSS_BODY_ASM4 "movq %6,%%r8;" -#define LSS_BODY_ASM6 LSS_BODY_ASM5 "movq %7,%%r9;" - -#undef LSS_BODY_CLOBBER0 -#undef LSS_BODY_CLOBBER1 -#undef LSS_BODY_CLOBBER2 -#undef LSS_BODY_CLOBBER3 -#undef LSS_BODY_CLOBBER4 -#undef LSS_BODY_CLOBBER5 -#undef LSS_BODY_CLOBBER6 -#define LSS_BODY_CLOBBER0 -#define LSS_BODY_CLOBBER1 LSS_BODY_CLOBBER0 -#define LSS_BODY_CLOBBER2 LSS_BODY_CLOBBER1 -#define LSS_BODY_CLOBBER3 LSS_BODY_CLOBBER2 -#define LSS_BODY_CLOBBER4 LSS_BODY_CLOBBER3 "r10", -#define LSS_BODY_CLOBBER5 LSS_BODY_CLOBBER4 "r8", -#define LSS_BODY_CLOBBER6 LSS_BODY_CLOBBER5 "r9", - -#undef LSS_BODY_ARG0 -#undef LSS_BODY_ARG1 -#undef LSS_BODY_ARG2 -#undef LSS_BODY_ARG3 -#undef LSS_BODY_ARG4 -#undef LSS_BODY_ARG5 -#undef LSS_BODY_ARG6 -#define LSS_BODY_ARG0() -#define LSS_BODY_ARG1(arg1) LSS_BODY_ARG0(), "D"(arg1) -#define LSS_BODY_ARG2(arg1, arg2) LSS_BODY_ARG1(arg1), "S"(arg2) -#define LSS_BODY_ARG3(arg1, arg2, arg3) LSS_BODY_ARG2(arg1, arg2), "d"(arg3) -#define LSS_BODY_ARG4(arg1, arg2, arg3, arg4) LSS_BODY_ARG3(arg1, arg2, arg3), "r"(arg4) -#define LSS_BODY_ARG5(arg1, arg2, arg3, arg4, arg5) LSS_BODY_ARG4(arg1, arg2, arg3, arg4), "r"(arg5) -#define LSS_BODY_ARG6(arg1, arg2, arg3, arg4, arg5, arg6) \ - LSS_BODY_ARG5(arg1, arg2, arg3, arg4, arg5), "r"(arg6) - -#undef _syscall0 -#define _syscall0(type, name) \ - type LSS_NAME(name)() { LSS_BODY(0, type, name); } -#undef _syscall1 -#define _syscall1(type, name, type1, arg1) \ - type LSS_NAME(name)(type1 arg1) { LSS_BODY(1, type, name, LSS_SYSCALL_ARG(arg1)); } -#undef _syscall2 -#define _syscall2(type, name, type1, arg1, type2, arg2) \ - type LSS_NAME(name)(type1 arg1, type2 arg2) { \ - LSS_BODY(2, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2)); \ - } -#undef _syscall3 -#define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ - LSS_BODY(3, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \ - LSS_SYSCALL_ARG(arg3)); \ - } -#undef _syscall4 -#define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - LSS_BODY(4, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \ - LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4)); \ - } -#undef _syscall5 -#define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - LSS_BODY(5, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \ - LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4), LSS_SYSCALL_ARG(arg5)); \ - } -#undef _syscall6 -#define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, \ - type6, arg6) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - LSS_BODY(6, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \ - LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4), LSS_SYSCALL_ARG(arg5), \ - LSS_SYSCALL_ARG(arg6)); \ - } -LSS_INLINE int LSS_NAME(clone)(int (*fn)(void*), void* child_stack, int flags, void* arg, - int* parent_tidptr, void* newtls, int* child_tidptr) { - long long __res; - { - __asm__ __volatile__(/* if (fn == NULL) - * return -EINVAL; - */ - "testq %4,%4\n" - "jz 1f\n" - - /* if (child_stack == NULL) - * return -EINVAL; - */ - "testq %5,%5\n" - "jz 1f\n" - - /* Set up alignment of the child stack: - * child_stack = (child_stack & ~0xF) - 16; - */ - "andq $-16,%5\n" - "subq $16,%5\n" - - /* Push "arg" and "fn" onto the stack that will be - * used by the child. - */ - "movq %7,8(%5)\n" - "movq %4,0(%5)\n" - - /* %rax = syscall(%rax = __NR_clone, - * %rdi = flags, - * %rsi = child_stack, - * %rdx = parent_tidptr, - * %r8 = new_tls, - * %r10 = child_tidptr) - */ - "movq %2,%%rax\n" - "movq %9,%%r8\n" - "movq %10,%%r10\n" - "syscall\n" - - /* if (%rax != 0) - * return; - */ - "testq %%rax,%%rax\n" - "jnz 1f\n" - - /* In the child. Terminate frame pointer chain. - */ - "xorq %%rbp,%%rbp\n" - - /* Call "fn(arg)". - */ - "popq %%rax\n" - "popq %%rdi\n" - "call *%%rax\n" - - /* Call _exit(%ebx). - */ - "movq %%rax,%%rdi\n" - "movq %3,%%rax\n" - "syscall\n" - - /* Return to parent. - */ - "1:\n" - : "=a"(__res) - : "0"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit), - "r"(LSS_SYSCALL_ARG(fn)), "S"(LSS_SYSCALL_ARG(child_stack)), - "D"(LSS_SYSCALL_ARG(flags)), "r"(LSS_SYSCALL_ARG(arg)), - "d"(LSS_SYSCALL_ARG(parent_tidptr)), "r"(LSS_SYSCALL_ARG(newtls)), - "r"(LSS_SYSCALL_ARG(child_tidptr)) - : "rsp", "memory", "r8", "r10", "r11", "rcx"); - } - LSS_RETURN(int, __res); -} - -LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) { - /* On x86-64, the kernel does not know how to return from - * a signal handler. Instead, it relies on user space to provide a - * restorer function that calls the rt_sigreturn() system call. - * Unfortunately, we cannot just reference the glibc version of this - * function, as glibc goes out of its way to make it inaccessible. - */ - long long res; - __asm__ __volatile__( - "call 2f\n" - "0:.align 16\n" - "1:movq %1,%%rax\n" - "syscall\n" - "2:popq %0\n" - "addq $(1b-0b),%0\n" - : "=a"(res) - : "i"(__NR_rt_sigreturn)); - return (void (*)(void))(uintptr_t)res; -} -#elif defined(__arm__) -/* Most definitions of _syscallX() neglect to mark "memory" as being - * clobbered. This causes problems with compilers, that do a better job - * at optimizing across __asm__ calls. - * So, we just have to redefine all fo the _syscallX() macros. - */ -#undef LSS_REG -#define LSS_REG(r, a) register long __r##r __asm__("r" #r) = (long)a - -/* r0..r3 are scratch registers and not preserved across function - * calls. We need to first evaluate the first 4 syscall arguments - * and store them on stack. They must be loaded into r0..r3 after - * all function calls to avoid r0..r3 being clobbered. - */ -#undef LSS_SAVE_ARG -#define LSS_SAVE_ARG(r, a) long __tmp##r = (long)a -#undef LSS_LOAD_ARG -#define LSS_LOAD_ARG(r) register long __r##r __asm__("r" #r) = __tmp##r - -#undef LSS_BODY -#define LSS_BODY(type, name, args...) \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __SYS_REG(name) \ - __asm__ __volatile__(__syscall_safe(name) \ - : "=r"(__res_r0) \ - : __SYS_REG_LIST(args) \ - : "lr", "memory"); \ - __res = __res_r0; \ - LSS_RETURN(type, __res) -#undef _syscall0 -#define _syscall0(type, name) \ - type LSS_NAME(name)() { LSS_BODY(type, name); } -#undef _syscall1 -#define _syscall1(type, name, type1, arg1) \ - type LSS_NAME(name)(type1 arg1) { \ - /* There is no need for using a volatile temp. */ \ - LSS_REG(0, arg1); \ - LSS_BODY(type, name, "r"(__r0)); \ - } -#undef _syscall2 -#define _syscall2(type, name, type1, arg1, type2, arg2) \ - type LSS_NAME(name)(type1 arg1, type2 arg2) { \ - LSS_SAVE_ARG(0, arg1); \ - LSS_SAVE_ARG(1, arg2); \ - LSS_LOAD_ARG(0); \ - LSS_LOAD_ARG(1); \ - LSS_BODY(type, name, "r"(__r0), "r"(__r1)); \ - } -#undef _syscall3 -#define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ - LSS_SAVE_ARG(0, arg1); \ - LSS_SAVE_ARG(1, arg2); \ - LSS_SAVE_ARG(2, arg3); \ - LSS_LOAD_ARG(0); \ - LSS_LOAD_ARG(1); \ - LSS_LOAD_ARG(2); \ - LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2)); \ - } -#undef _syscall4 -#define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - LSS_SAVE_ARG(0, arg1); \ - LSS_SAVE_ARG(1, arg2); \ - LSS_SAVE_ARG(2, arg3); \ - LSS_SAVE_ARG(3, arg4); \ - LSS_LOAD_ARG(0); \ - LSS_LOAD_ARG(1); \ - LSS_LOAD_ARG(2); \ - LSS_LOAD_ARG(3); \ - LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3)); \ - } -#undef _syscall5 -#define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - LSS_SAVE_ARG(0, arg1); \ - LSS_SAVE_ARG(1, arg2); \ - LSS_SAVE_ARG(2, arg3); \ - LSS_SAVE_ARG(3, arg4); \ - LSS_REG(4, arg5); \ - LSS_LOAD_ARG(0); \ - LSS_LOAD_ARG(1); \ - LSS_LOAD_ARG(2); \ - LSS_LOAD_ARG(3); \ - LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), "r"(__r4)); \ - } -#undef _syscall6 -#define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, \ - type6, arg6) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - LSS_SAVE_ARG(0, arg1); \ - LSS_SAVE_ARG(1, arg2); \ - LSS_SAVE_ARG(2, arg3); \ - LSS_SAVE_ARG(3, arg4); \ - LSS_REG(4, arg5); \ - LSS_REG(5, arg6); \ - LSS_LOAD_ARG(0); \ - LSS_LOAD_ARG(1); \ - LSS_LOAD_ARG(2); \ - LSS_LOAD_ARG(3); \ - LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), "r"(__r4), "r"(__r5)); \ - } -LSS_INLINE int LSS_NAME(clone)(int (*fn)(void*), void* child_stack, int flags, void* arg, - int* parent_tidptr, void* newtls, int* child_tidptr) { - register long __res __asm__("r5"); - { - if (fn == NULL || child_stack == NULL) { - __res = -EINVAL; - goto clone_exit; - } - - /* stash first 4 arguments on stack first because we can only load - * them after all function calls. - */ - int tmp_flags = flags; - int* tmp_stack = (int*)child_stack; - void* tmp_ptid = parent_tidptr; - void* tmp_tls = newtls; - - register int* __ctid __asm__("r4") = child_tidptr; - - /* Push "arg" and "fn" onto the stack that will be - * used by the child. - */ - *(--tmp_stack) = (int)arg; - *(--tmp_stack) = (int)fn; - - /* We must load r0..r3 last after all possible function calls. */ - register int __flags __asm__("r0") = tmp_flags; - register void* __stack __asm__("r1") = tmp_stack; - register void* __ptid __asm__("r2") = tmp_ptid; - register void* __tls __asm__("r3") = tmp_tls; - - /* %r0 = syscall(%r0 = flags, - * %r1 = child_stack, - * %r2 = parent_tidptr, - * %r3 = newtls, - * %r4 = child_tidptr) - */ - __SYS_REG(clone) - __asm__ __volatile__(/* %r0 = syscall(%r0 = flags, - * %r1 = child_stack, - * %r2 = parent_tidptr, - * %r3 = newtls, - * %r4 = child_tidptr) - */ - "push {r7}\n" - "mov r7,%1\n" - __syscall(clone)"\n" - - /* if (%r0 != 0) - * return %r0; - */ - "movs %0,r0\n" - "bne 1f\n" - - /* In the child, now. Call "fn(arg)". - */ - "ldr r0,[sp, #4]\n" - "mov lr,pc\n" - "ldr pc,[sp]\n" - - /* Call _exit(%r0), which never returns. We only - * need to set r7 for EABI syscall ABI but we do - * this always to simplify code sharing between - * old and new syscall ABIs. - */ - "mov r7,%2\n" - __syscall(exit)"\n" - - /* Pop r7 from the stack only in the parent. - */ - "1: pop {r7}\n" - : "=r" (__res) - : "r"(__sysreg), - "i"(__NR_exit), "r"(__stack), "r"(__flags), - "r"(__ptid), "r"(__tls), "r"(__ctid) - : "cc", "lr", "memory"); - } -clone_exit: - LSS_RETURN(int, __res); -} -#elif defined(__mips__) -#undef LSS_REG -#define LSS_REG(r, a) register unsigned long __r##r __asm__("$" #r) = (unsigned long)(a) - -#if _MIPS_SIM == _MIPS_SIM_ABI32 -// See http://sources.redhat.com/ml/libc-alpha/2004-10/msg00050.html -// or http://www.linux-mips.org/archives/linux-mips/2004-10/msg00142.html -#define MIPS_SYSCALL_CLOBBERS \ - "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "memory" -#else -#define MIPS_SYSCALL_CLOBBERS \ - "$1", "$3", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "memory" -#endif - -#undef LSS_BODY -#define LSS_BODY(type, name, r7, ...) \ - register unsigned long __v0 __asm__("$2") = __NR_##name; \ - __asm__ __volatile__("syscall\n" \ - : "=&r"(__v0), r7(__r7) \ - : "0"(__v0), ##__VA_ARGS__ \ - : MIPS_SYSCALL_CLOBBERS); \ - LSS_RETURN(type, __v0, __r7) -#undef _syscall0 -#define _syscall0(type, name) \ - type LSS_NAME(name)() { \ - register unsigned long __r7 __asm__("$7"); \ - LSS_BODY(type, name, "=r"); \ - } -#undef _syscall1 -#define _syscall1(type, name, type1, arg1) \ - type LSS_NAME(name)(type1 arg1) { \ - register unsigned long __r7 __asm__("$7"); \ - LSS_REG(4, arg1); \ - LSS_BODY(type, name, "=r", "r"(__r4)); \ - } -#undef _syscall2 -#define _syscall2(type, name, type1, arg1, type2, arg2) \ - type LSS_NAME(name)(type1 arg1, type2 arg2) { \ - register unsigned long __r7 __asm__("$7"); \ - LSS_REG(4, arg1); \ - LSS_REG(5, arg2); \ - LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5)); \ - } -#undef _syscall3 -#define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ - register unsigned long __r7 __asm__("$7"); \ - LSS_REG(4, arg1); \ - LSS_REG(5, arg2); \ - LSS_REG(6, arg3); \ - LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5), "r"(__r6)); \ - } -#undef _syscall4 -#define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - LSS_REG(4, arg1); \ - LSS_REG(5, arg2); \ - LSS_REG(6, arg3); \ - LSS_REG(7, arg4); \ - LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6)); \ - } -#undef _syscall5 -#if _MIPS_SIM == _MIPS_SIM_ABI32 -/* The old 32bit MIPS system call API passes the fifth and sixth argument - * on the stack, whereas the new APIs use registers "r8" and "r9". - */ -#define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - LSS_REG(4, arg1); \ - LSS_REG(5, arg2); \ - LSS_REG(6, arg3); \ - LSS_REG(7, arg4); \ - register unsigned long __v0 __asm__("$2"); \ - __asm__ __volatile__( \ - ".set noreorder\n" \ - "lw $2, %6\n" \ - "subu $29, 32\n" \ - "sw $2, 16($29)\n" \ - "li $2, %2\n" \ - "syscall\n" \ - "addiu $29, 32\n" \ - ".set reorder\n" \ - : "=&r"(__v0), "+r"(__r7) \ - : "i"(__NR_##name), "r"(__r4), "r"(__r5), "r"(__r6), "m"((unsigned long)arg5) \ - : MIPS_SYSCALL_CLOBBERS); \ - LSS_RETURN(type, __v0, __r7); \ - } -#else -#define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - LSS_REG(4, arg1); \ - LSS_REG(5, arg2); \ - LSS_REG(6, arg3); \ - LSS_REG(7, arg4); \ - LSS_REG(8, arg5); \ - LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), "r"(__r8)); \ - } -#endif -#undef _syscall6 -#if _MIPS_SIM == _MIPS_SIM_ABI32 -/* The old 32bit MIPS system call API passes the fifth and sixth argument - * on the stack, whereas the new APIs use registers "r8" and "r9". - */ -#define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, \ - type6, arg6) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - LSS_REG(4, arg1); \ - LSS_REG(5, arg2); \ - LSS_REG(6, arg3); \ - LSS_REG(7, arg4); \ - register unsigned long __v0 __asm__("$2"); \ - __asm__ __volatile__( \ - ".set noreorder\n" \ - "lw $2, %6\n" \ - "lw $8, %7\n" \ - "subu $29, 32\n" \ - "sw $2, 16($29)\n" \ - "sw $8, 20($29)\n" \ - "li $2, %2\n" \ - "syscall\n" \ - "addiu $29, 32\n" \ - ".set reorder\n" \ - : "=&r"(__v0), "+r"(__r7) \ - : "i"(__NR_##name), "r"(__r4), "r"(__r5), "r"(__r6), "m"((unsigned long)arg5), \ - "m"((unsigned long)arg6) \ - : MIPS_SYSCALL_CLOBBERS); \ - LSS_RETURN(type, __v0, __r7); \ - } -#else -#define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, \ - type6, arg6) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - LSS_REG(4, arg1); \ - LSS_REG(5, arg2); \ - LSS_REG(6, arg3); \ - LSS_REG(7, arg4); \ - LSS_REG(8, arg5); \ - LSS_REG(9, arg6); \ - LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), "r"(__r8), "r"(__r9)); \ - } -#endif -LSS_INLINE int LSS_NAME(clone)(int (*fn)(void*), void* child_stack, int flags, void* arg, - int* parent_tidptr, void* newtls, int* child_tidptr) { - register unsigned long __v0 __asm__("$2"); - register unsigned long __r7 __asm__("$7") = (unsigned long)newtls; - { - register int __flags __asm__("$4") = flags; - register void* __stack __asm__("$5") = child_stack; - register void* __ptid __asm__("$6") = parent_tidptr; - register int* __ctid __asm__("$8") = child_tidptr; - __asm__ __volatile__( -#if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 - "subu $29,24\n" -#elif _MIPS_SIM == _MIPS_SIM_NABI32 - "sub $29,16\n" -#else - "dsubu $29,16\n" -#endif - - /* if (fn == NULL || child_stack == NULL) - * return -EINVAL; - */ - "li %0,%2\n" - "beqz %5,1f\n" - "beqz %6,1f\n" - - /* Push "arg" and "fn" onto the stack that will be - * used by the child. - */ -#if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 - "subu %6,32\n" - "sw %5,0(%6)\n" - "sw %8,4(%6)\n" -#elif _MIPS_SIM == _MIPS_SIM_NABI32 - "sub %6,32\n" - "sw %5,0(%6)\n" - "sw %8,8(%6)\n" -#else - "dsubu %6,32\n" - "sd %5,0(%6)\n" - "sd %8,8(%6)\n" -#endif - - /* $7 = syscall($4 = flags, - * $5 = child_stack, - * $6 = parent_tidptr, - * $7 = newtls, - * $8 = child_tidptr) - */ - "li $2,%3\n" - "syscall\n" - - /* if ($7 != 0) - * return $2; - */ - "bnez $7,1f\n" - "bnez $2,1f\n" - - /* In the child, now. Call "fn(arg)". - */ -#if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 - "lw $25,0($29)\n" - "lw $4,4($29)\n" -#elif _MIPS_SIM == _MIPS_SIM_NABI32 - "lw $25,0($29)\n" - "lw $4,8($29)\n" -#else - "ld $25,0($29)\n" - "ld $4,8($29)\n" -#endif - "jalr $25\n" - - /* Call _exit($2) - */ - "move $4,$2\n" - "li $2,%4\n" - "syscall\n" - - "1:\n" -#if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 - "addu $29, 24\n" -#elif _MIPS_SIM == _MIPS_SIM_NABI32 - "add $29, 16\n" -#else - "daddu $29,16\n" -#endif - : "=&r"(__v0), "=r"(__r7) - : "i"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit), "r"(fn), "r"(__stack), - "r"(__flags), "r"(arg), "r"(__ptid), "r"(__r7), "r"(__ctid) - : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "memory"); - } - LSS_RETURN(int, __v0, __r7); -} -#elif defined(__PPC__) -#undef LSS_LOADARGS_0 -#define LSS_LOADARGS_0(name, dummy...) __sc_0 = __NR_##name -#undef LSS_LOADARGS_1 -#define LSS_LOADARGS_1(name, arg1) \ - LSS_LOADARGS_0(name); \ - __sc_3 = (unsigned long)(arg1) -#undef LSS_LOADARGS_2 -#define LSS_LOADARGS_2(name, arg1, arg2) \ - LSS_LOADARGS_1(name, arg1); \ - __sc_4 = (unsigned long)(arg2) -#undef LSS_LOADARGS_3 -#define LSS_LOADARGS_3(name, arg1, arg2, arg3) \ - LSS_LOADARGS_2(name, arg1, arg2); \ - __sc_5 = (unsigned long)(arg3) -#undef LSS_LOADARGS_4 -#define LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4) \ - LSS_LOADARGS_3(name, arg1, arg2, arg3); \ - __sc_6 = (unsigned long)(arg4) -#undef LSS_LOADARGS_5 -#define LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \ - LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4); \ - __sc_7 = (unsigned long)(arg5) -#undef LSS_LOADARGS_6 -#define LSS_LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ - LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \ - __sc_8 = (unsigned long)(arg6) -#undef LSS_ASMINPUT_0 -#define LSS_ASMINPUT_0 "0"(__sc_0) -#undef LSS_ASMINPUT_1 -#define LSS_ASMINPUT_1 LSS_ASMINPUT_0, "1"(__sc_3) -#undef LSS_ASMINPUT_2 -#define LSS_ASMINPUT_2 LSS_ASMINPUT_1, "2"(__sc_4) -#undef LSS_ASMINPUT_3 -#define LSS_ASMINPUT_3 LSS_ASMINPUT_2, "3"(__sc_5) -#undef LSS_ASMINPUT_4 -#define LSS_ASMINPUT_4 LSS_ASMINPUT_3, "4"(__sc_6) -#undef LSS_ASMINPUT_5 -#define LSS_ASMINPUT_5 LSS_ASMINPUT_4, "5"(__sc_7) -#undef LSS_ASMINPUT_6 -#define LSS_ASMINPUT_6 LSS_ASMINPUT_5, "6"(__sc_8) -#undef LSS_BODY -#define LSS_BODY(nr, type, name, args...) \ - long __sc_ret, __sc_err; \ - { \ - register unsigned long __sc_0 __asm__("r0"); \ - register unsigned long __sc_3 __asm__("r3"); \ - register unsigned long __sc_4 __asm__("r4"); \ - register unsigned long __sc_5 __asm__("r5"); \ - register unsigned long __sc_6 __asm__("r6"); \ - register unsigned long __sc_7 __asm__("r7"); \ - register unsigned long __sc_8 __asm__("r8"); \ - \ - LSS_LOADARGS_##nr(name, args); \ - __asm__ __volatile__( \ - "sc\n\t" \ - "mfcr %0" \ - : "=&r"(__sc_0), "=&r"(__sc_3), "=&r"(__sc_4), "=&r"(__sc_5), "=&r"(__sc_6), \ - "=&r"(__sc_7), "=&r"(__sc_8) \ - : LSS_ASMINPUT_##nr \ - : "cr0", "ctr", "memory", "r9", "r10", "r11", "r12"); \ - __sc_ret = __sc_3; \ - __sc_err = __sc_0; \ - } \ - LSS_RETURN(type, __sc_ret, __sc_err) -#undef _syscall0 -#define _syscall0(type, name) \ - type LSS_NAME(name)(void) { LSS_BODY(0, type, name); } -#undef _syscall1 -#define _syscall1(type, name, type1, arg1) \ - type LSS_NAME(name)(type1 arg1) { LSS_BODY(1, type, name, arg1); } -#undef _syscall2 -#define _syscall2(type, name, type1, arg1, type2, arg2) \ - type LSS_NAME(name)(type1 arg1, type2 arg2) { LSS_BODY(2, type, name, arg1, arg2); } -#undef _syscall3 -#define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ - LSS_BODY(3, type, name, arg1, arg2, arg3); \ - } -#undef _syscall4 -#define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - LSS_BODY(4, type, name, arg1, arg2, arg3, arg4); \ - } -#undef _syscall5 -#define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - LSS_BODY(5, type, name, arg1, arg2, arg3, arg4, arg5); \ - } -#undef _syscall6 -#define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, \ - type6, arg6) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - LSS_BODY(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \ - } -/* clone function adapted from glibc 2.18 clone.S */ -LSS_INLINE int LSS_NAME(clone)(int (*fn)(void*), void* child_stack, int flags, void* arg, - int* parent_tidptr, void* newtls, int* child_tidptr) { - long __ret, __err; - { -#if defined(__PPC64__) - -/* Stack frame offsets. */ -#if _CALL_ELF != 2 -#define FRAME_MIN_SIZE 112 -#define FRAME_TOC_SAVE 40 -#else -#define FRAME_MIN_SIZE 32 -#define FRAME_TOC_SAVE 24 -#endif - - register int (*__fn)(void*) __asm__("r3") = fn; - register void* __cstack __asm__("r4") = child_stack; - register int __flags __asm__("r5") = flags; - register void* __arg __asm__("r6") = arg; - register int* __ptidptr __asm__("r7") = parent_tidptr; - register void* __newtls __asm__("r8") = newtls; - register int* __ctidptr __asm__("r9") = child_tidptr; - __asm__ __volatile__( - /* check for fn == NULL - * and child_stack == NULL - */ - "cmpdi cr0, %6, 0\n\t" - "cmpdi cr1, %7, 0\n\t" - "cror cr0*4+eq, cr1*4+eq, cr0*4+eq\n\t" - "beq- cr0, 1f\n\t" - - /* set up stack frame for child */ - "clrrdi %7, %7, 4\n\t" - "li 0, 0\n\t" - "stdu 0, -%13(%7)\n\t" - - /* fn, arg, child_stack are saved acrVoss the syscall */ - "mr 28, %6\n\t" - "mr 29, %7\n\t" - "mr 27, %9\n\t" - - /* syscall - r3 == flags - r4 == child_stack - r5 == parent_tidptr - r6 == newtls - r7 == child_tidptr */ - "mr 3, %8\n\t" - "mr 5, %10\n\t" - "mr 6, %11\n\t" - "mr 7, %12\n\t" - "li 0, %4\n\t" - "sc\n\t" - - /* Test if syscall was successful */ - "cmpdi cr1, 3, 0\n\t" - "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t" - "bne- cr1, 1f\n\t" - - /* Do the function call */ - "std 2, %14(1)\n\t" -#if _CALL_ELF != 2 - "ld 0, 0(28)\n\t" - "ld 2, 8(28)\n\t" - "mtctr 0\n\t" -#else - "mr 12, 28\n\t" - "mtctr 12\n\t" -#endif - "mr 3, 27\n\t" - "bctrl\n\t" - "ld 2, %14(1)\n\t" - - /* Call _exit(r3) */ - "li 0, %5\n\t" - "sc\n\t" - - /* Return to parent */ - "1:\n\t" - "mr %0, 3\n\t" - : "=r"(__ret), "=r"(__err) - : "0"(-1), "i"(EINVAL), "i"(__NR_clone), "i"(__NR_exit), "r"(__fn), "r"(__cstack), - "r"(__flags), "r"(__arg), "r"(__ptidptr), "r"(__newtls), "r"(__ctidptr), - "i"(FRAME_MIN_SIZE), "i"(FRAME_TOC_SAVE) - : "cr0", "cr1", "memory", "ctr", "r0", "r29", "r27", "r28"); -#else - register int (*__fn)(void*) __asm__("r8") = fn; - register void* __cstack __asm__("r4") = child_stack; - register int __flags __asm__("r3") = flags; - register void* __arg __asm__("r9") = arg; - register int* __ptidptr __asm__("r5") = parent_tidptr; - register void* __newtls __asm__("r6") = newtls; - register int* __ctidptr __asm__("r7") = child_tidptr; - __asm__ __volatile__( - /* check for fn == NULL - * and child_stack == NULL - */ - "cmpwi cr0, %6, 0\n\t" - "cmpwi cr1, %7, 0\n\t" - "cror cr0*4+eq, cr1*4+eq, cr0*4+eq\n\t" - "beq- cr0, 1f\n\t" - - /* set up stack frame for child */ - "clrrwi %7, %7, 4\n\t" - "li 0, 0\n\t" - "stwu 0, -16(%7)\n\t" - - /* fn, arg, child_stack are saved across the syscall: r28-30 */ - "mr 28, %6\n\t" - "mr 29, %7\n\t" - "mr 27, %9\n\t" - - /* syscall */ - "li 0, %4\n\t" - /* flags already in r3 - * child_stack already in r4 - * ptidptr already in r5 - * newtls already in r6 - * ctidptr already in r7 - */ - "sc\n\t" - - /* Test if syscall was successful */ - "cmpwi cr1, 3, 0\n\t" - "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t" - "bne- cr1, 1f\n\t" - - /* Do the function call */ - "mtctr 28\n\t" - "mr 3, 27\n\t" - "bctrl\n\t" - - /* Call _exit(r3) */ - "li 0, %5\n\t" - "sc\n\t" - - /* Return to parent */ - "1:\n" - "mfcr %1\n\t" - "mr %0, 3\n\t" - : "=r"(__ret), "=r"(__err) - : "0"(-1), "1"(EINVAL), "i"(__NR_clone), "i"(__NR_exit), "r"(__fn), "r"(__cstack), - "r"(__flags), "r"(__arg), "r"(__ptidptr), "r"(__newtls), "r"(__ctidptr) - : "cr0", "cr1", "memory", "ctr", "r0", "r29", "r27", "r28"); - -#endif - } - LSS_RETURN(int, __ret, __err); -} -#elif defined(__aarch64__) -#undef LSS_REG -#define LSS_REG(r, a) register long __x##r __asm__("x" #r) = (long)a -#undef LSS_BODY -#define LSS_BODY(type, name, args...) \ - register long __res_x0 __asm__("x0"); \ - long __res; \ - __asm__ __volatile__( \ - "mov x8, %1\n" \ - "svc 0x0\n" \ - : "=r"(__res_x0) \ - : "i"(__NR_##name), ##args \ - : "memory"); \ - __res = __res_x0; \ - LSS_RETURN(type, __res) -#undef _syscall0 -#define _syscall0(type, name) \ - type LSS_NAME(name)(void) { LSS_BODY(type, name); } -#undef _syscall1 -#define _syscall1(type, name, type1, arg1) \ - type LSS_NAME(name)(type1 arg1) { \ - LSS_REG(0, arg1); \ - LSS_BODY(type, name, "r"(__x0)); \ - } -#undef _syscall2 -#define _syscall2_long(type, name, svc, type1, arg1, type2, arg2) \ - type LSS_NAME(name)(type1 arg1, type2 arg2) { \ - LSS_REG(0, arg1); \ - LSS_REG(1, arg2); \ - LSS_BODY(type, svc, "r"(__x0), "r"(__x1)); \ - } -#define _syscall2(type, name, type1, arg1, type2, arg2) \ - _syscall2_long(type, name, name, type1, arg1, type2, arg2) -#undef _syscall3 -#define _syscall3_long(type, name, svc, type1, arg1, type2, arg2, type3, arg3) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ - LSS_REG(0, arg1); \ - LSS_REG(1, arg2); \ - LSS_REG(2, arg3); \ - LSS_BODY(type, svc, "r"(__x0), "r"(__x1), "r"(__x2)); \ - } -#define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ - _syscall3_long(type, name, name, type1, arg1, type2, arg2, type3, arg3) -#undef _syscall4 -#define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - LSS_REG(0, arg1); \ - LSS_REG(1, arg2); \ - LSS_REG(2, arg3); \ - LSS_REG(3, arg4); \ - LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2), "r"(__x3)); \ - } -#undef _syscall5 -#define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - LSS_REG(0, arg1); \ - LSS_REG(1, arg2); \ - LSS_REG(2, arg3); \ - LSS_REG(3, arg4); \ - LSS_REG(4, arg5); \ - LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2), "r"(__x3), "r"(__x4)); \ - } -#undef _syscall6 -#define _syscall6_long(type, name, svc, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, \ - arg5, type6, arg6) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - LSS_REG(0, arg1); \ - LSS_REG(1, arg2); \ - LSS_REG(2, arg3); \ - LSS_REG(3, arg4); \ - LSS_REG(4, arg5); \ - LSS_REG(5, arg6); \ - LSS_BODY(type, svc, "r"(__x0), "r"(__x1), "x"(__x2), "r"(__x3), "r"(__x4), "r"(__x5)); \ - } -#define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, \ - type6, arg6) \ - _syscall6_long(type, name, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, \ - arg5, type6, arg6) -/* clone function adapted from glibc 2.18 clone.S */ -LSS_INLINE int LSS_NAME(clone)(int (*fn)(void*), void* child_stack, int flags, void* arg, - int* parent_tidptr, void* newtls, int* child_tidptr) { - long __res; - { - register int (*__fn)(void*) __asm__("x0") = fn; - register void* __stack __asm__("x1") = child_stack; - register int __flags __asm__("x2") = flags; - register void* __arg __asm__("x3") = arg; - register int* __ptid __asm__("x4") = parent_tidptr; - register void* __tls __asm__("x5") = newtls; - register int* __ctid __asm__("x6") = child_tidptr; - __asm__ __volatile__(/* if (fn == NULL || child_stack == NULL) - * return -EINVAL; - */ - "cbz x0,1f\n" - "cbz x1,1f\n" - - /* Push "arg" and "fn" onto the stack that will be - * used by the child. - */ - "stp x0,x3, [x1, #-16]!\n" - - "mov x0,x2\n" /* flags */ - "mov x2,x4\n" /* ptid */ - "mov x3,x5\n" /* tls */ - "mov x4,x6\n" /* ctid */ - "mov x8,%9\n" /* clone */ - - "svc 0x0\n" - - /* if (%r0 != 0) - * return %r0; - */ - "cmp x0, #0\n" - "bne 2f\n" - - /* In the child, now. Call "fn(arg)". - */ - "ldp x1, x0, [sp], #16\n" - "blr x1\n" - - /* Call _exit(%r0). - */ - "mov x8, %10\n" - "svc 0x0\n" - "1:\n" - "mov x8, %1\n" - "2:\n" - : "=r"(__res) - : "i"(-EINVAL), "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg), - "r"(__ptid), "r"(__tls), "r"(__ctid), "i"(__NR_clone), "i"(__NR_exit) - : "x30", "memory"); - } - LSS_RETURN(int, __res); -} -#elif defined(__s390__) -#undef LSS_REG -#define LSS_REG(r, a) register unsigned long __r##r __asm__("r" #r) = (unsigned long)a -#undef LSS_BODY -#define LSS_BODY(type, name, args...) \ - register unsigned long __nr __asm__("r1") = (unsigned long)(__NR_##name); \ - register long __res_r2 __asm__("r2"); \ - long __res; \ - __asm__ __volatile__("svc 0\n\t" : "=d"(__res_r2) : "d"(__nr), ##args : "memory"); \ - __res = __res_r2; \ - LSS_RETURN(type, __res) -#undef _syscall0 -#define _syscall0(type, name) \ - type LSS_NAME(name)(void) { LSS_BODY(type, name); } -#undef _syscall1 -#define _syscall1(type, name, type1, arg1) \ - type LSS_NAME(name)(type1 arg1) { \ - LSS_REG(2, arg1); \ - LSS_BODY(type, name, "0"(__r2)); \ - } -#undef _syscall2 -#define _syscall2(type, name, type1, arg1, type2, arg2) \ - type LSS_NAME(name)(type1 arg1, type2 arg2) { \ - LSS_REG(2, arg1); \ - LSS_REG(3, arg2); \ - LSS_BODY(type, name, "0"(__r2), "d"(__r3)); \ - } -#undef _syscall3 -#define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ - LSS_REG(2, arg1); \ - LSS_REG(3, arg2); \ - LSS_REG(4, arg3); \ - LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4)); \ - } -#undef _syscall4 -#define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - LSS_REG(2, arg1); \ - LSS_REG(3, arg2); \ - LSS_REG(4, arg3); \ - LSS_REG(5, arg4); \ - LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), "d"(__r5)); \ - } -#undef _syscall5 -#define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - LSS_REG(2, arg1); \ - LSS_REG(3, arg2); \ - LSS_REG(4, arg3); \ - LSS_REG(5, arg4); \ - LSS_REG(6, arg5); \ - LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), "d"(__r5), "d"(__r6)); \ - } -#undef _syscall6 -#define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, \ - type6, arg6) \ - type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - LSS_REG(2, arg1); \ - LSS_REG(3, arg2); \ - LSS_REG(4, arg3); \ - LSS_REG(5, arg4); \ - LSS_REG(6, arg5); \ - LSS_REG(7, arg6); \ - LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), "d"(__r5), "d"(__r6), "d"(__r7)); \ - } -LSS_INLINE int LSS_NAME(clone)(int (*fn)(void*), void* child_stack, int flags, void* arg, - int* parent_tidptr, void* newtls, int* child_tidptr) { - long __ret; - { - register int (*__fn)(void*) __asm__("r1") = fn; - register void* __cstack __asm__("r2") = child_stack; - register int __flags __asm__("r3") = flags; - register void* __arg __asm__("r0") = arg; - register int* __ptidptr __asm__("r4") = parent_tidptr; - register void* __newtls __asm__("r6") = newtls; - register int* __ctidptr __asm__("r5") = child_tidptr; - __asm__ __volatile__( -#ifndef __s390x__ - /* arg already in r0 */ - "ltr %4, %4\n\t" /* check fn, which is already in r1 */ - "jz 1f\n\t" /* NULL function pointer, return -EINVAL */ - "ltr %5, %5\n\t" /* check child_stack, which is already in r2 */ - "jz 1f\n\t" /* NULL stack pointer, return -EINVAL */ - /* flags already in r3 */ - /* parent_tidptr already in r4 */ - /* child_tidptr already in r5 */ - /* newtls already in r6 */ - "svc %2\n\t" /* invoke clone syscall */ - "ltr %0,%%r2\n\t" /* load return code into __ret and test */ - "jnz 1f\n\t" /* return to parent if non-zero */ - /* start child thread */ - "lr %%r2, %7\n\t" /* set first parameter to void *arg */ - "ahi %%r15, -96\n\t" /* make room on the stack for the save area */ - "xc 0(4,%%r15), 0(%%r15)\n\t" - "basr %%r14, %4\n\t" /* jump to fn */ - "svc %3\n" /* invoke exit syscall */ - "1:\n" -#else - /* arg already in r0 */ - "ltgr %4, %4\n\t" /* check fn, which is already in r1 */ - "jz 1f\n\t" /* NULL function pointer, return -EINVAL */ - "ltgr %5, %5\n\t" /* check child_stack, which is already in r2 */ - "jz 1f\n\t" /* NULL stack pointer, return -EINVAL */ - /* flags already in r3 */ - /* parent_tidptr already in r4 */ - /* child_tidptr already in r5 */ - /* newtls already in r6 */ - "svc %2\n\t" /* invoke clone syscall */ - "ltgr %0, %%r2\n\t" /* load return code into __ret and test */ - "jnz 1f\n\t" /* return to parent if non-zero */ - /* start child thread */ - "lgr %%r2, %7\n\t" /* set first parameter to void *arg */ - "aghi %%r15, -160\n\t" /* make room on the stack for the save area */ - "xc 0(8,%%r15), 0(%%r15)\n\t" - "basr %%r14, %4\n\t" /* jump to fn */ - "svc %3\n" /* invoke exit syscall */ - "1:\n" -#endif - : "=r"(__ret) - : "0"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit), "d"(__fn), "d"(__cstack), - "d"(__flags), "d"(__arg), "d"(__ptidptr), "d"(__newtls), "d"(__ctidptr) - : "cc", "r14", "memory"); - } - LSS_RETURN(int, __ret); -} -#endif -#define __NR__exit __NR_exit -#define __NR__gettid __NR_gettid -#define __NR__mremap __NR_mremap -LSS_INLINE _syscall1(int, close, int, f) LSS_INLINE _syscall1(int, _exit, int, e) -#if defined(__aarch64__) && defined(__ILP32__) - /* aarch64_ilp32 uses fcntl64 for sys_fcntl() */ - LSS_INLINE _syscall3_long(int, fcntl, fcntl64, int, f, int, c, long, a) -#else - LSS_INLINE _syscall3(int, fcntl, int, f, int, c, long, a) -#endif -#if defined(__aarch64__) && defined(__ILP32__) - /* aarch64_ilp32 uses fstat64 for sys_fstat() */ - LSS_INLINE _syscall2_long(int, fstat, fstat64, int, f, struct kernel_stat*, b) -#else - LSS_INLINE - _syscall2(int, fstat, int, f, struct kernel_stat*, b) -#endif - LSS_INLINE _syscall6(int, futex, int*, a, int, o, int, v, struct kernel_timespec*, - t, int*, a2, int, v3) -#ifdef __NR_getdents64 - LSS_INLINE - _syscall3(int, getdents64, int, f, struct kernel_dirent64*, d, int, c) -#define KERNEL_DIRENT kernel_dirent64 -#define GETDENTS sys_getdents64 -#else - LSS_INLINE - _syscall3(int, getdents, int, f, struct kernel_dirent*, d, int, c) -#define KERNEL_DIRENT kernel_dirent -#define GETDENTS sys_getdents -#endif - LSS_INLINE _syscall0(pid_t, getpid) LSS_INLINE _syscall0(pid_t, getppid) LSS_INLINE - _syscall0(pid_t, _gettid) LSS_INLINE _syscall2(int, kill, pid_t, p, int, s) -#if defined(__x86_64__) - /* Need to make sure off_t isn't truncated to 32-bits under x32. */ - LSS_INLINE off_t LSS_NAME(lseek)(int f, off_t o, int w) { - _LSS_BODY(3, off_t, lseek, off_t, LSS_SYSCALL_ARG(f), (uint64_t)(o), LSS_SYSCALL_ARG(w)); -} -#elif defined(__aarch64__) && defined(__ILP32__) - /* aarch64_ilp32 uses llseek for sys_lseek() */ - LSS_INLINE _syscall3_long(off_t, lseek, llseek, int, f, off_t, o, int, w) -#else - LSS_INLINE _syscall3(off_t, lseek, int, f, off_t, o, int, w) -#endif -LSS_INLINE _syscall2(int, munmap, void*, s, size_t, l) LSS_INLINE - _syscall5(void*, _mremap, void*, o, size_t, os, size_t, ns, unsigned long, f, void*, - a) LSS_INLINE _syscall2(int, prctl, int, o, long, a) LSS_INLINE - _syscall4(long, ptrace, int, r, pid_t, p, void*, a, void*, d) LSS_INLINE - _syscall3(ssize_t, read, int, f, void*, b, size_t, c) LSS_INLINE - _syscall4(int, rt_sigaction, int, s, const struct kernel_sigaction*, a, - struct kernel_sigaction*, o, size_t, c) LSS_INLINE - _syscall4(int, rt_sigprocmask, int, h, const struct kernel_sigset_t*, s, - struct kernel_sigset_t*, o, size_t, c); -LSS_INLINE _syscall0(int, sched_yield) LSS_INLINE - _syscall2(int, sigaltstack, const stack_t*, s, const stack_t*, o) -#if defined(__NR_fstatat) - LSS_INLINE _syscall4(int, fstatat, int, d, const char*, p, struct kernel_stat*, b, - int, flags) LSS_INLINE - int LSS_NAME(stat)(const char* p, struct kernel_stat* b) { - return LSS_NAME(fstatat)(AT_FDCWD, p, b, 0); -} -#else - LSS_INLINE _syscall2(int, stat, const char*, f, struct kernel_stat*, b) -#endif -LSS_INLINE _syscall3(ssize_t, write, int, f, const void*, b, size_t, c) -#if defined(__NR_getcpu) - LSS_INLINE _syscall3(long, getcpu, unsigned*, cpu, unsigned*, node, void*, unused); -#endif -#if defined(__x86_64__) || defined(__aarch64__) || \ - (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32) -LSS_INLINE _syscall3(int, socket, int, d, int, t, int, p) -#endif -#if defined(__x86_64__) || defined(__s390x__) - LSS_INLINE int LSS_NAME(sigaction)(int signum, const struct kernel_sigaction* act, - struct kernel_sigaction* oldact) { -#if defined(__x86_64__) - /* On x86_64, the kernel requires us to always set our own - * SA_RESTORER in order to be able to return from a signal handler. - * This function must have a "magic" signature that the "gdb" - * (and maybe the kernel?) can recognize. - */ - if (act != NULL && !(act->sa_flags & SA_RESTORER)) { - struct kernel_sigaction a = *act; - a.sa_flags |= SA_RESTORER; - a.sa_restorer = LSS_NAME(restore_rt)(); - return LSS_NAME(rt_sigaction)(signum, &a, oldact, (KERNEL_NSIG + 7) / 8); - } else -#endif - return LSS_NAME(rt_sigaction)(signum, act, oldact, (KERNEL_NSIG + 7) / 8); -} - -LSS_INLINE int LSS_NAME(sigprocmask)(int how, const struct kernel_sigset_t* set, - struct kernel_sigset_t* oldset) { - return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG + 7) / 8); -} -#endif -#if (defined(__aarch64__)) || \ - (defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32)) -LSS_INLINE int LSS_NAME(sigaction)(int signum, const struct kernel_sigaction* act, - struct kernel_sigaction* oldact) { - return LSS_NAME(rt_sigaction)(signum, act, oldact, (KERNEL_NSIG + 7) / 8); -} -LSS_INLINE int LSS_NAME(sigprocmask)(int how, const struct kernel_sigset_t* set, - struct kernel_sigset_t* oldset) { - return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG + 7) / 8); -} -#endif -#ifdef __NR_wait4 -LSS_INLINE _syscall4(pid_t, wait4, pid_t, p, int*, s, int, o, struct kernel_rusage*, - r) LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int* status, int options) { - return LSS_NAME(wait4)(pid, status, options, 0); -} -#else - LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p, int*, s, int, o) -#endif -#ifdef __NR_openat -LSS_INLINE _syscall4(int, openat, int, d, const char*, p, int, f, int, m) LSS_INLINE - int LSS_NAME(open)(const char* p, int f, int m) { - return LSS_NAME(openat)(AT_FDCWD, p, f, m); -} -#else - LSS_INLINE - _syscall3(int, open, const char*, p, int, f, int, m) -#endif -LSS_INLINE int LSS_NAME(sigemptyset)(struct kernel_sigset_t* set) { - memset(&set->sig, 0, sizeof(set->sig)); - return 0; -} - -LSS_INLINE int LSS_NAME(sigfillset)(struct kernel_sigset_t* set) { - memset(&set->sig, -1, sizeof(set->sig)); - return 0; -} - -LSS_INLINE int LSS_NAME(sigaddset)(struct kernel_sigset_t* set, int signum) { - if (signum < 1 || signum > (int)(8 * sizeof(set->sig))) { - LSS_ERRNO = EINVAL; - return -1; - } else { - set->sig[(signum - 1) / (8 * sizeof(set->sig[0]))] |= - 1UL << ((signum - 1) % (8 * sizeof(set->sig[0]))); - return 0; - } -} - -LSS_INLINE int LSS_NAME(sigdelset)(struct kernel_sigset_t* set, int signum) { - if (signum < 1 || signum > (int)(8 * sizeof(set->sig))) { - LSS_ERRNO = EINVAL; - return -1; - } else { - set->sig[(signum - 1) / (8 * sizeof(set->sig[0]))] &= - ~(1UL << ((signum - 1) % (8 * sizeof(set->sig[0])))); - return 0; - } -} - -#if defined(__i386__) || defined(__arm__) || \ - (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || defined(__PPC__) || \ - (defined(__s390__) && !defined(__s390x__)) -#define __NR__sigaction __NR_sigaction -#define __NR__sigprocmask __NR_sigprocmask -LSS_INLINE _syscall2(int, fstat64, int, f, struct kernel_stat64*, b) LSS_INLINE - _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t*, res, uint, wh) -#if defined(__s390__) && !defined(__s390x__) - /* On s390, mmap2() arguments are passed in memory. */ - LSS_INLINE void* LSS_NAME(_mmap2)(void* s, size_t l, int p, int f, int d, off_t o) { - unsigned long buf[6] = {(unsigned long)s, (unsigned long)l, (unsigned long)p, - (unsigned long)f, (unsigned long)d, (unsigned long)o}; - LSS_REG(2, buf); - LSS_BODY(void*, mmap2, "0"(__r2)); -} -#elif !defined(__PPC64__) -#define __NR__mmap2 __NR_mmap2 - LSS_INLINE - _syscall6(void*, _mmap2, void*, s, size_t, l, int, p, int, f, int, d, off_t, o) -#endif -LSS_INLINE _syscall3(int, _sigaction, int, s, const struct kernel_old_sigaction*, a, - struct kernel_old_sigaction*, o) LSS_INLINE - _syscall3(int, _sigprocmask, int, h, const unsigned long*, s, unsigned long*, o) LSS_INLINE - _syscall2(int, stat64, const char*, p, struct kernel_stat64*, b) - - LSS_INLINE int LSS_NAME(sigaction)(int signum, const struct kernel_sigaction* act, - struct kernel_sigaction* oldact) { - int old_errno = LSS_ERRNO; - int rc; - struct kernel_sigaction a; - if (act != NULL) { - a = *act; -#ifdef __i386__ - /* On i386, the kernel requires us to always set our own - * SA_RESTORER when using realtime signals. Otherwise, it does not - * know how to return from a signal handler. This function must have - * a "magic" signature that the "gdb" (and maybe the kernel?) can - * recognize. - * Apparently, a SA_RESTORER is implicitly set by the kernel, when - * using non-realtime signals. - * - * TODO: Test whether ARM needs a restorer - */ - if (!(a.sa_flags & SA_RESTORER)) { - a.sa_flags |= SA_RESTORER; - a.sa_restorer = - (a.sa_flags & SA_SIGINFO) ? LSS_NAME(restore_rt)() : LSS_NAME(restore)(); - } -#endif - } - rc = LSS_NAME(rt_sigaction)(signum, act ? &a : act, oldact, (KERNEL_NSIG + 7) / 8); - if (rc < 0 && LSS_ERRNO == ENOSYS) { - struct kernel_old_sigaction oa, ooa, *ptr_a = &oa, *ptr_oa = &ooa; - if (!act) { - ptr_a = NULL; - } else { - oa.sa_handler_ = act->sa_handler_; - memcpy(&oa.sa_mask, &act->sa_mask, sizeof(oa.sa_mask)); -#ifndef __mips__ - oa.sa_restorer = act->sa_restorer; -#endif - oa.sa_flags = act->sa_flags; - } - if (!oldact) { - ptr_oa = NULL; - } - LSS_ERRNO = old_errno; - rc = LSS_NAME(_sigaction)(signum, ptr_a, ptr_oa); - if (rc == 0 && oldact) { - if (act) { - memcpy(oldact, act, sizeof(*act)); - } else { - memset(oldact, 0, sizeof(*oldact)); - } - oldact->sa_handler_ = ptr_oa->sa_handler_; - oldact->sa_flags = ptr_oa->sa_flags; - memcpy(&oldact->sa_mask, &ptr_oa->sa_mask, sizeof(ptr_oa->sa_mask)); -#ifndef __mips__ - oldact->sa_restorer = ptr_oa->sa_restorer; -#endif - } - } - return rc; -} - -LSS_INLINE int LSS_NAME(sigprocmask)(int how, const struct kernel_sigset_t* set, - struct kernel_sigset_t* oldset) { - int olderrno = LSS_ERRNO; - int rc = LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG + 7) / 8); - if (rc < 0 && LSS_ERRNO == ENOSYS) { - LSS_ERRNO = olderrno; - if (oldset) { - LSS_NAME(sigemptyset)(oldset); - } - rc = LSS_NAME(_sigprocmask)(how, set ? &set->sig[0] : NULL, - oldset ? &oldset->sig[0] : NULL); - } - return rc; -} -#endif -#if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \ - (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \ - (defined(__PPC__) && !defined(__PPC64__)) || (defined(__s390__) && !defined(__s390x__)) -/* On these architectures, implement mmap() with mmap2(). */ -LSS_INLINE void* LSS_NAME(mmap)(void* s, size_t l, int p, int f, int d, int64_t o) { - if (o % 4096) { - LSS_ERRNO = EINVAL; - return (void*)-1; - } - return LSS_NAME(_mmap2)(s, l, p, f, d, (o / 4096)); -} -#elif defined(__s390x__) -/* On s390x, mmap() arguments are passed in memory. */ -LSS_INLINE void* LSS_NAME(mmap)(void* s, size_t l, int p, int f, int d, int64_t o) { - unsigned long buf[6] = {(unsigned long)s, (unsigned long)l, (unsigned long)p, - (unsigned long)f, (unsigned long)d, (unsigned long)o}; - LSS_REG(2, buf); - LSS_BODY(void*, mmap, "0"(__r2)); -} -#elif defined(__x86_64__) -/* Need to make sure __off64_t isn't truncated to 32-bits under x32. */ -LSS_INLINE void* LSS_NAME(mmap)(void* s, size_t l, int p, int f, int d, int64_t o) { - LSS_BODY(6, void*, mmap, LSS_SYSCALL_ARG(s), LSS_SYSCALL_ARG(l), LSS_SYSCALL_ARG(p), - LSS_SYSCALL_ARG(f), LSS_SYSCALL_ARG(d), (uint64_t)(o)); -} -#elif defined(__aarch64__) && defined(__ILP32__) -/* aarch64_ilp32 uses mmap2 for sys_mmap() */ -LSS_INLINE _syscall6_long(void*, mmap, mmap2, void*, addr, size_t, length, int, prot, int, flags, - int, fd, int64_t, offset) -#else -/* Remaining 64-bit architectures. */ -LSS_INLINE _syscall6(void*, mmap, void*, addr, size_t, length, int, prot, int, flags, int, fd, - int64_t, offset) -#endif -#if defined(__i386__) || defined(__PPC__) || (defined(__arm__) && !defined(__ARM_EABI__)) || \ - (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || defined(__s390__) - -/* See sys_socketcall in net/socket.c in kernel source. - * It de-multiplexes on its first arg and unpacks the arglist - * array in its second arg. - */ -LSS_INLINE _syscall2(int, socketcall, int, c, unsigned long*, a) - - LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) { - unsigned long args[3] = {(unsigned long)domain, (unsigned long)type, (unsigned long)protocol}; - return LSS_NAME(socketcall)(1, args); -} -#elif defined(__ARM_EABI__) -LSS_INLINE _syscall3(int, socket, int, d, int, t, int, p) -#endif -#if defined(__mips__) -/* sys_pipe() on MIPS has non-standard calling conventions, as it returns - * both file handles through CPU registers. - */ -LSS_INLINE int LSS_NAME(pipe)(int* p) { - register unsigned long __v0 __asm__("$2") = __NR_pipe; - register unsigned long __v1 __asm__("$3"); - register unsigned long __r7 __asm__("$7"); - __asm__ __volatile__("syscall\n" - : "=&r"(__v0), "=&r"(__v1), "+r"(__r7) - : "0"(__v0) - : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "memory"); - if (__r7) { - LSS_ERRNO = __v0; - return -1; - } else { - p[0] = __v0; - p[1] = __v1; - return 0; - } -} -#elif defined(__NR_pipe2) - LSS_INLINE _syscall2(int, pipe2, int*, p, int, f) LSS_INLINE int LSS_NAME(pipe)(int* p) { - return LSS_NAME(pipe2)(p, 0); -} -#else -LSS_INLINE _syscall1(int, pipe, int*, p) -#endif - -LSS_INLINE pid_t LSS_NAME(gettid)() { - pid_t tid = LSS_NAME(_gettid)(); - if (tid != -1) { - return tid; - } - return LSS_NAME(getpid)(); -} - -LSS_INLINE void* LSS_NAME(mremap)(void* old_address, size_t old_size, size_t new_size, int flags, - ...) { - va_list ap; - void *new_address, *rc; - va_start(ap, flags); - new_address = va_arg(ap, void*); - rc = LSS_NAME(_mremap)(old_address, old_size, new_size, flags, new_address); - va_end(ap); - return rc; -} - -LSS_INLINE int LSS_NAME(ptrace_detach)(pid_t pid) { - /* PTRACE_DETACH can sometimes forget to wake up the tracee and it - * then sends job control signals to the real parent, rather than to - * the tracer. We reduce the risk of this happening by starting a - * whole new time slice, and then quickly sending a SIGCONT signal - * right after detaching from the tracee. - */ - int rc, err; - LSS_NAME(sched_yield)(); - rc = LSS_NAME(ptrace)(PTRACE_DETACH, pid, (void*)0, (void*)0); - err = LSS_ERRNO; - LSS_NAME(kill)(pid, SIGCONT); - LSS_ERRNO = err; - return rc; -} -#endif - -#if defined(__cplusplus) && !defined(SYS_CPLUSPLUS) -} -#endif - -#endif -#endif diff --git a/be/src/gutil/spinlock_internal.cc b/be/src/gutil/spinlock_internal.cc deleted file mode 100644 index 8dd0c416f0..0000000000 --- a/be/src/gutil/spinlock_internal.cc +++ /dev/null @@ -1,125 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- -/* Copyright (c) 2010, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// The OS-specific header included below must provide two calls: -// base::internal::SpinLockDelay() and base::internal::SpinLockWake(). -// See spinlock_internal.h for the spec of SpinLockWake(). - -// void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) -// SpinLockDelay() generates an appropriate spin delay on iteration "loop" of a -// spin loop on location *w, whose previously observed value was "value". -// SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick, -// or may wait for a delay that can be truncated by a call to SpinlockWake(w). -// In all cases, it must return in bounded time even if SpinlockWake() is not -// called. - -#include "gutil/spinlock_internal.h" - -// forward declaration for use by spinlock_*-inl.h -namespace base { -namespace internal { -static int SuggestedDelayNS(int loop); -} -} // namespace base - -#if defined(_WIN32) -#include "gutil/spinlock_win32-inl.h" -#elif defined(__linux__) -#include "gutil/spinlock_linux-inl.h" -#else -#include "gutil/spinlock_posix-inl.h" -#endif - -namespace base { -namespace internal { - -// See spinlock_internal.h for spec. -int32 SpinLockWait(volatile Atomic32* w, int n, const SpinLockWaitTransition trans[]) { - int32 v; - bool done = false; - for (int loop = 0; !done; loop++) { - v = base::subtle::Acquire_Load(w); - int i; - for (i = 0; i != n && v != trans[i].from; i++) { - } - if (i == n) { - SpinLockDelay(w, v, loop); // no matching transition - } else if (trans[i].to == v || // null transition - base::subtle::Acquire_CompareAndSwap(w, v, trans[i].to) == v) { - done = trans[i].done; - } - } - return v; -} - -// Return a suggested delay in nanoseconds for iteration number "loop" -static int SuggestedDelayNS(int loop) { - // Weak pseudo-random number generator to get some spread between threads - // when many are spinning. -#ifdef BASE_HAS_ATOMIC64 - static base::subtle::Atomic64 rand; - uint64 r = base::subtle::NoBarrier_Load(&rand); - r = 0x5deece66dLL * r + 0xb; // numbers from nrand48() - base::subtle::NoBarrier_Store(&rand, r); - - r <<= 16; // 48-bit random number now in top 48-bits. - if (loop < 0 || loop > 32) { // limit loop to 0..32 - loop = 32; - } - // loop>>3 cannot exceed 4 because loop cannot exceed 32. - // Select top 20..24 bits of lower 48 bits, - // giving approximately 0ms to 16ms. - // Mean is exponential in loop for first 32 iterations, then 8ms. - // The futex path multiplies this by 16, since we expect explicit wakeups - // almost always on that path. - return r >> (44 - (loop >> 3)); -#else - static Atomic32 rand; - uint32 r = base::subtle::NoBarrier_Load(&rand); - r = 0x343fd * r + 0x269ec3; // numbers from MSVC++ - base::subtle::NoBarrier_Store(&rand, r); - - r <<= 1; // 31-bit random number now in top 31-bits. - if (loop < 0 || loop > 32) { // limit loop to 0..32 - loop = 32; - } - // loop>>3 cannot exceed 4 because loop cannot exceed 32. - // Select top 20..24 bits of lower 31 bits, - // giving approximately 0ms to 16ms. - // Mean is exponential in loop for first 32 iterations, then 8ms. - // The futex path multiplies this by 16, since we expect explicit wakeups - // almost always on that path. - return r >> (12 - (loop >> 3)); -#endif -} - -} // namespace internal -} // namespace base diff --git a/be/src/gutil/spinlock_internal.h b/be/src/gutil/spinlock_internal.h deleted file mode 100644 index 212d6523d9..0000000000 --- a/be/src/gutil/spinlock_internal.h +++ /dev/null @@ -1,61 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- -/* Copyright (c) 2010, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * --- - * This file is an internal part spinlock.cc and once.cc - * It may not be used directly by code outside of //base. - */ - -#pragma once - -#include "gutil/atomicops.h" -#include "gutil/integral_types.h" - -namespace base { -namespace internal { - -// SpinLockWait() waits until it can perform one of several transitions from -// "from" to "to". It returns when it performs a transition where done==true. -struct SpinLockWaitTransition { - int32 from; - int32 to; - bool done; -}; - -// Wait until *w can transition from trans[i].from to trans[i].to for some i -// satisfying 0<=i -#include -#include -#include - -#include "gutil/linux_syscall_support.h" - -#define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 -#define FUTEX_PRIVATE_FLAG 128 - -static bool have_futex; -static int futex_private_flag = FUTEX_PRIVATE_FLAG; - -namespace { -static struct InitModule { - InitModule() { - int x = 0; - // futexes are ints, so we can use them only when - // that's the same size as the lockword_ in SpinLock. - have_futex = (sizeof(Atomic32) == sizeof(int) && - sys_futex(&x, FUTEX_WAKE, 1, NULL, NULL, 0) >= 0); - if (have_futex && sys_futex(&x, FUTEX_WAKE | futex_private_flag, 1, NULL, NULL, 0) < 0) { - futex_private_flag = 0; - } - } -} init_module; - -} // anonymous namespace - -namespace base { -namespace internal { - -void SpinLockDelay(volatile Atomic32* w, int32 value, int loop) { - if (loop != 0) { - int save_errno = errno; - struct timespec tm; - tm.tv_sec = 0; - if (have_futex) { - tm.tv_nsec = base::internal::SuggestedDelayNS(loop); - } else { - tm.tv_nsec = 2000001; // above 2ms so linux 2.4 doesn't spin - } - if (have_futex) { - tm.tv_nsec *= 16; // increase the delay; we expect explicit wakeups - sys_futex(reinterpret_cast(const_cast(w)), - FUTEX_WAIT | futex_private_flag, value, - reinterpret_cast(&tm), NULL, 0); - } else { - nanosleep(&tm, NULL); - } - errno = save_errno; - } -} - -void SpinLockWake(volatile Atomic32* w, bool all) { - if (have_futex) { - sys_futex(reinterpret_cast(const_cast(w)), FUTEX_WAKE | futex_private_flag, - all ? INT_MAX : 1, NULL, NULL, 0); - } -} - -} // namespace internal -} // namespace base diff --git a/be/src/gutil/spinlock_posix-inl.h b/be/src/gutil/spinlock_posix-inl.h deleted file mode 100644 index 9fc372fa1e..0000000000 --- a/be/src/gutil/spinlock_posix-inl.h +++ /dev/null @@ -1,61 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- -/* Copyright (c) 2009, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * --- - * This file is a Posix-specific part of spinlock_internal.cc - */ - -#include -#if defined(HAVE_SCHED_H) || defined(__APPLE__) -#include /* For sched_yield() */ -#endif -#include /* For nanosleep() */ - -namespace base { -namespace internal { - -void SpinLockDelay(volatile Atomic32* w, int32 value, int loop) { - int save_errno = errno; - if (loop == 0) { - } else if (loop == 1) { - sched_yield(); - } else { - struct timespec tm; - tm.tv_sec = 0; - tm.tv_nsec = base::internal::SuggestedDelayNS(loop); - nanosleep(&tm, NULL); - } - errno = save_errno; -} - -void SpinLockWake(volatile Atomic32* w, bool all) {} - -} // namespace internal -} // namespace base diff --git a/be/src/gutil/spinlock_win32-inl.h b/be/src/gutil/spinlock_win32-inl.h deleted file mode 100644 index 26375252f0..0000000000 --- a/be/src/gutil/spinlock_win32-inl.h +++ /dev/null @@ -1,52 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- -/* Copyright (c) 2009, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * --- - * This file is a Win32-specific part of spinlock_internal.cc - */ - -#include - -namespace base { -namespace internal { - -void SpinLockDelay(volatile Atomic32* w, int32 value, int loop) { - if (loop == 0) { - } else if (loop == 1) { - Sleep(0); - } else { - Sleep(base::internal::SuggestedDelayNS(loop) / 1000000); - } -} - -void SpinLockWake(volatile Atomic32* w, bool all) {} - -} // namespace internal -} // namespace base diff --git a/be/src/gutil/valgrind.h b/be/src/gutil/valgrind.h deleted file mode 100644 index ecce0944b3..0000000000 --- a/be/src/gutil/valgrind.h +++ /dev/null @@ -1,3716 +0,0 @@ -/* -*- c -*- - ---------------------------------------------------------------- - - Notice that the following BSD-style license applies to this one - file (valgrind.h) only. The rest of Valgrind is licensed under the - terms of the GNU General Public License, version 2, unless - otherwise indicated. See the COPYING file in the source - distribution for details. - - ---------------------------------------------------------------- - - This file is part of Valgrind, a dynamic binary instrumentation - framework. - - Copyright (C) 2000-2008 Julian Seward. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - ---------------------------------------------------------------- - - Notice that the above BSD-style license applies to this one file - (valgrind.h) only. The entire rest of Valgrind is licensed under - the terms of the GNU General Public License, version 2. See the - COPYING file in the source distribution for details. - - ---------------------------------------------------------------- -*/ - -/* This file is for inclusion into client (your!) code. - - You can use these macros to manipulate and query Valgrind's - execution inside your own programs. - - The resulting executables will still run without Valgrind, just a - little bit more slowly than they otherwise would, but otherwise - unchanged. When not running on valgrind, each client request - consumes very few (eg. 7) instructions, so the resulting performance - loss is negligible unless you plan to execute client requests - millions of times per second. Nevertheless, if that is still a - problem, you can compile with the NVALGRIND symbol defined (gcc - -DNVALGRIND) so that client requests are not even compiled in. */ - -#ifndef __VALGRIND_H -#define __VALGRIND_H - -#include - -/* Nb: this file might be included in a file compiled with -ansi. So - we can't use C++ style "//" comments nor the "asm" keyword (instead - use "__asm__"). */ - -/* Derive some tags indicating what the target platform is. Note - that in this file we're using the compiler's CPP symbols for - identifying architectures, which are different to the ones we use - within the rest of Valgrind. Note, __powerpc__ is active for both - 32 and 64-bit PPC, whereas __powerpc64__ is only active for the - latter (on Linux, that is). */ -#undef PLAT_x86_linux -#undef PLAT_amd64_linux -#undef PLAT_ppc32_linux -#undef PLAT_ppc64_linux -#undef PLAT_ppc32_aix5 -#undef PLAT_ppc64_aix5 - -#if !defined(_AIX) && defined(__i386__) -#define PLAT_x86_linux 1 -#elif !defined(_AIX) && defined(__x86_64__) -#define PLAT_amd64_linux 1 -#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__) -#define PLAT_ppc32_linux 1 -#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__) -#define PLAT_ppc64_linux 1 -#elif defined(_AIX) && defined(__64BIT__) -#define PLAT_ppc64_aix5 1 -#elif defined(_AIX) && !defined(__64BIT__) -#define PLAT_ppc32_aix5 1 -#endif - -/* If we're not compiling for our target platform, don't generate - any inline asms. */ -#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) && !defined(PLAT_ppc32_linux) && \ - !defined(PLAT_ppc64_linux) && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5) -#if !defined(NVALGRIND) -#define NVALGRIND 1 -#endif -#endif - -/* ------------------------------------------------------------------ */ -/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ -/* in here of use to end-users -- skip to the next section. */ -/* ------------------------------------------------------------------ */ - -#if defined(NVALGRIND) - -/* Define NVALGRIND to completely remove the Valgrind magic sequence - from the compiled code (analogous to NDEBUG's effects on - assert()) */ -#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, _zzq_arg1, _zzq_arg2, \ - _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { (_zzq_rlval) = (_zzq_default); } - -#else /* ! NVALGRIND */ - -/* The following defines the magic code sequences which the JITter - spots and handles magically. Don't look too closely at them as - they will rot your brain. - - The assembly code sequences for all architectures is in this one - file. This is because this file must be stand-alone, and we don't - want to have multiple files. - - For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default - value gets put in the return slot, so that everything works when - this is executed not under Valgrind. Args are passed in a memory - block, and so there's no intrinsic limit to the number that could - be passed, but it's currently five. - - The macro args are: - _zzq_rlval result lvalue - _zzq_default default value (result returned when running on real CPU) - _zzq_request request code - _zzq_arg1..5 request params - - The other two macros are used to support function wrapping, and are - a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the - guest's NRADDR pseudo-register and whatever other information is - needed to safely run the call original from the wrapper: on - ppc64-linux, the R2 value at the divert point is also needed. This - information is abstracted into a user-visible type, OrigFn. - - VALGRIND_CALL_NOREDIR_* behaves the same as the following on the - guest, but guarantees that the branch instruction will not be - redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: - branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a - complete inline asm, since it needs to be combined with more magic - inline asm stuff to be useful. -*/ - -/* ------------------------- x86-linux ------------------------- */ - -#if defined(PLAT_x86_linux) - -typedef struct { - unsigned int nraddr; /* where's the code? */ -} OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "roll $3, %%edi ; roll $13, %%edi\n\t" \ - "roll $29, %%edi ; roll $19, %%edi\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, _zzq_arg1, _zzq_arg2, \ - _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { \ - volatile unsigned int _zzq_args[6]; \ - volatile unsigned int _zzq_result; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %EDX = client_request ( %EAX ) */ \ - "xchgl %%ebx,%%ebx" \ - : "=d"(_zzq_result) \ - : "a"(&_zzq_args[0]), "0"(_zzq_default) \ - : "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { \ - volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %EAX = guest_NRADDR */ \ - "xchgl %%ecx,%%ecx" \ - : "=a"(__addr) \ - : \ - : "cc", "memory"); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_EAX \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* call-noredir *%EAX */ \ - "xchgl %%edx,%%edx\n\t" -#endif /* PLAT_x86_linux */ - -/* ------------------------ amd64-linux ------------------------ */ - -#if defined(PLAT_amd64_linux) - -typedef struct { - unsigned long long int nraddr; /* where's the code? */ -} OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ - "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, _zzq_arg1, _zzq_arg2, \ - _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { \ - volatile unsigned long long int _zzq_args[6]; \ - volatile unsigned long long int _zzq_result; \ - _zzq_args[0] = (unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %RDX = client_request ( %RAX ) */ \ - "xchgq %%rbx,%%rbx" \ - : "=d"(_zzq_result) \ - : "a"(&_zzq_args[0]), "0"(_zzq_default) \ - : "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { \ - volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned long long int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %RAX = guest_NRADDR */ \ - "xchgq %%rcx,%%rcx" \ - : "=a"(__addr) \ - : \ - : "cc", "memory"); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_RAX \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* call-noredir *%RAX */ \ - "xchgq %%rdx,%%rdx\n\t" -#endif /* PLAT_amd64_linux */ - -/* ------------------------ ppc32-linux ------------------------ */ - -#if defined(PLAT_ppc32_linux) - -typedef struct { - unsigned int nraddr; /* where's the code? */ -} OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, _zzq_arg1, _zzq_arg2, \ - _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { \ - unsigned int _zzq_args[6]; \ - unsigned int _zzq_result; \ - unsigned int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile( \ - "mr 3,%1\n\t" /*default*/ \ - "mr 4,%2\n\t" /*ptr*/ \ - __SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" /*result*/ \ - : "=b"(_zzq_result) \ - : "b"(_zzq_default), "b"(_zzq_ptr) \ - : "cc", "memory", "r3", "r4"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { \ - volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b"(__addr) \ - : \ - : "cc", "memory", "r3"); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" -#endif /* PLAT_ppc32_linux */ - -/* ------------------------ ppc64-linux ------------------------ */ - -#if defined(PLAT_ppc64_linux) - -typedef struct { - unsigned long long int nraddr; /* where's the code? */ - unsigned long long int r2; /* what tocptr do we need? */ -} OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ - "rotldi 0,0,61 ; rotldi 0,0,51\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, _zzq_arg1, _zzq_arg2, \ - _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { \ - unsigned long long int _zzq_args[6]; \ - register unsigned long long int _zzq_result __asm__("r3"); \ - register unsigned long long int* _zzq_ptr __asm__("r4"); \ - _zzq_args[0] = (unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1" \ - : "=r"(_zzq_result) \ - : "0"(_zzq_default), "r"(_zzq_ptr) \ - : "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { \ - volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned long long int __addr __asm__("r3"); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = guest_NRADDR */ \ - "or 2,2,2" \ - : "=r"(__addr) \ - : \ - : "cc", "memory"); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4" \ - : "=r"(__addr) \ - : \ - : "cc", "memory"); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc64_linux */ - -/* ------------------------ ppc32-aix5 ------------------------- */ - -#if defined(PLAT_ppc32_aix5) - -typedef struct { - unsigned int nraddr; /* where's the code? */ - unsigned int r2; /* what tocptr do we need? */ -} OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, _zzq_arg1, _zzq_arg2, \ - _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { \ - unsigned int _zzq_args[7]; \ - register unsigned int _zzq_result; \ - register unsigned int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - _zzq_args[6] = (unsigned int)(_zzq_default); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile( \ - "mr 4,%1\n\t" \ - "lwz 3, 24(4)\n\t" __SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" \ - : "=b"(_zzq_result) \ - : "b"(_zzq_ptr) \ - : "r3", "r4", "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { \ - volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b"(__addr) \ - : \ - : "r3", "cc", "memory"); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4\n\t" \ - "mr %0,3" \ - : "=b"(__addr) \ - : \ - : "r3", "cc", "memory"); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc32_aix5 */ - -/* ------------------------ ppc64-aix5 ------------------------- */ - -#if defined(PLAT_ppc64_aix5) - -typedef struct { - unsigned long long int nraddr; /* where's the code? */ - unsigned long long int r2; /* what tocptr do we need? */ -} OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ - "rotldi 0,0,61 ; rotldi 0,0,51\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, _zzq_arg1, _zzq_arg2, \ - _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { \ - unsigned long long int _zzq_args[7]; \ - register unsigned long long int _zzq_result; \ - register unsigned long long int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int long long)(_zzq_request); \ - _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \ - _zzq_args[6] = (unsigned int long long)(_zzq_default); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile( \ - "mr 4,%1\n\t" \ - "ld 3, 48(4)\n\t" __SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" \ - : "=b"(_zzq_result) \ - : "b"(_zzq_ptr) \ - : "r3", "r4", "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { \ - volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned long long int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b"(__addr) \ - : \ - : "r3", "cc", "memory"); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4\n\t" \ - "mr %0,3" \ - : "=b"(__addr) \ - : \ - : "r3", "cc", "memory"); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc64_aix5 */ - -/* Insert assembly code for other platforms here... */ - -#endif /* NVALGRIND */ - -/* ------------------------------------------------------------------ */ -/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ -/* ugly. It's the least-worst tradeoff I can think of. */ -/* ------------------------------------------------------------------ */ - -/* This section defines magic (a.k.a appalling-hack) macros for doing - guaranteed-no-redirection macros, so as to get from function - wrappers to the functions they are wrapping. The whole point is to - construct standard call sequences, but to do the call itself with a - special no-redirect call pseudo-instruction that the JIT - understands and handles specially. This section is long and - repetitious, and I can't see a way to make it shorter. - - The naming scheme is as follows: - - CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} - - 'W' stands for "word" and 'v' for "void". Hence there are - different macros for calling arity 0, 1, 2, 3, 4, etc, functions, - and for each, the possibility of returning a word-typed result, or - no result. -*/ - -/* Use these to write the name of your wrapper. NOTE: duplicates - VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ - -#define I_WRAP_SONAME_FNNAME_ZU(soname, fnname) _vgwZU_##soname##_##fnname - -#define I_WRAP_SONAME_FNNAME_ZZ(soname, fnname) _vgwZZ_##soname##_##fnname - -/* Use this macro from within a wrapper function to collect the - context (address and possibly other info) of the original function. - Once you have that you can then use it in one of the CALL_FN_ - macros. The type of the argument _lval is OrigFn. */ -#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) - -/* Derivatives of the main macros below, for calling functions - returning void. */ - -#define CALL_FN_v_v(fnptr) \ - do { \ - volatile unsigned long _junk; \ - CALL_FN_W_v(_junk, fnptr); \ - } while (0) - -#define CALL_FN_v_W(fnptr, arg1) \ - do { \ - volatile unsigned long _junk; \ - CALL_FN_W_W(_junk, fnptr, arg1); \ - } while (0) - -#define CALL_FN_v_WW(fnptr, arg1, arg2) \ - do { \ - volatile unsigned long _junk; \ - CALL_FN_W_WW(_junk, fnptr, arg1, arg2); \ - } while (0) - -#define CALL_FN_v_WWW(fnptr, arg1, arg2, arg3) \ - do { \ - volatile unsigned long _junk; \ - CALL_FN_W_WWW(_junk, fnptr, arg1, arg2, arg3); \ - } while (0) - -/* ------------------------- x86-linux ------------------------- */ - -#if defined(PLAT_x86_linux) - -/* These regs are trashed by the hidden call. No need to mention eax - as gcc can already see that, plus causes gcc to bomb. */ -#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" - -/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile("movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $4, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1, arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $8, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $12, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $16, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $20, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $24, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $28, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $32, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $36, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $40, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "pushl 44(%%eax)\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $44, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11, arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "pushl 48(%%eax)\n\t" \ - "pushl 44(%%eax)\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX "addl $48, %%esp\n" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#endif /* PLAT_x86_linux */ - -/* ------------------------ amd64-linux ------------------------ */ - -#if defined(PLAT_amd64_linux) - -/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11" - -/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned - long) == 8. */ - -/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ - macros. In order not to trash the stack redzone, we need to drop - %rsp by 128 before the hidden call, and restore afterwards. The - nastyness is that it is only by luck that the stack still appears - to be unwindable during the hidden call - since then the behaviour - of any routine using this macro does not match what the CFI data - says. Sigh. - - Why is this important? Imagine that a wrapper has a stack - allocated local, and passes to the hidden call, a pointer to it. - Because gcc does not know about the hidden call, it may allocate - that local in the redzone. Unfortunately the hidden call may then - trash it before it comes to use it. So we must step clear of the - redzone, for the duration of the hidden call, to make it safe. - - Probably the same problem afflicts the other redzone-style ABIs too - (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is - self describing (none of this CFI nonsense) so at least messing - with the stack pointer doesn't give a danger of non-unwindable - stack. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1, arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - "addq $128,%%rsp\n\t" VALGRIND_CALL_NOREDIR_RAX \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $8, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $16, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $24, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $32, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 88(%%rax)\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $40, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11, arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 96(%%rax)\n\t" \ - "pushq 88(%%rax)\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $48, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a"(_res) \ - : /*in*/ "a"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#endif /* PLAT_amd64_linux */ - -/* ------------------------ ppc32-linux ------------------------ */ - -#if defined(PLAT_ppc32_linux) - -/* This is useful for finding out about the on-stack stuff: - - extern int f9 ( int,int,int,int,int,int,int,int,int ); - extern int f10 ( int,int,int,int,int,int,int,int,int,int ); - extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); - extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); - - int g9 ( void ) { - return f9(11,22,33,44,55,66,77,88,99); - } - int g10 ( void ) { - return f10(11,22,33,44,55,66,77,88,99,110); - } - int g11 ( void ) { - return f11(11,22,33,44,55,66,77,88,99,110,121); - } - int g12 ( void ) { - return f12(11,22,33,44,55,66,77,88,99,110,121,132); - } -*/ - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "r0", "r2", "r3", \ - "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13" - -/* These CALL_FN_ macros assume that on ppc32-linux, - sizeof(unsigned long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1, arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-16\n\t" /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,16\n\t" \ - "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-16\n\t" /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,16\n\t" \ - "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - _argvec[11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-32\n\t" /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,16(1)\n\t" /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,32\n\t" \ - "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11, arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - _argvec[11] = (unsigned long)arg11; \ - _argvec[12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-32\n\t" /* arg12 */ \ - "lwz 3,48(11)\n\t" \ - "stw 3,20(1)\n\t" /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,16(1)\n\t" /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,32\n\t" \ - "mr %0,3" \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#endif /* PLAT_ppc32_linux */ - -/* ------------------------ ppc64-linux ------------------------ */ - -#if defined(PLAT_ppc64_linux) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "r0", "r2", "r3", \ - "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13" - -/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned - long) == 8. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1, arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-128\n\t" /* expand stack frame */ /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,128" /* restore frame */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - _argvec[2 + 10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-128\n\t" /* expand stack frame */ /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,128" /* restore frame */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - _argvec[2 + 10] = (unsigned long)arg10; \ - _argvec[2 + 11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-144\n\t" /* expand stack frame */ /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,144" /* restore frame */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11, arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - _argvec[2 + 10] = (unsigned long)arg10; \ - _argvec[2 + 11] = (unsigned long)arg11; \ - _argvec[2 + 12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-144\n\t" /* expand stack frame */ /* arg12 */ \ - "ld 3,96(11)\n\t" \ - "std 3,136(1)\n\t" /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,144" /* restore frame */ \ - : /*out*/ "=r"(_res) \ - : /*in*/ "r"(&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#endif /* PLAT_ppc64_linux */ - -/* ------------------------ ppc32-aix5 ------------------------- */ - -#if defined(PLAT_ppc32_aix5) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "r0", "r2", "r3", \ - "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13" - -/* Expand the stack frame, copying enough info that unwinding - still works. Trashes r3. */ - -#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ - "addi 1,1,-" #_n_fr \ - "\n\t" \ - "lwz 3," #_n_fr \ - "(1)\n\t" \ - "stw 3,0(1)\n\t" - -#define VG_CONTRACT_FRAME_BY(_n_fr) "addi 1,1," #_n_fr "\n\t" - -/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1, arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(64) \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(64) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - _argvec[2 + 10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(64) \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(64) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - _argvec[2 + 10] = (unsigned long)arg10; \ - _argvec[2 + 11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(72) \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,64(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(72) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11, arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - _argvec[2 + 10] = (unsigned long)arg10; \ - _argvec[2 + 11] = (unsigned long)arg11; \ - _argvec[2 + 12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(72) \ - /* arg12 */ \ - "lwz 3,48(11)\n\t" \ - "stw 3,68(1)\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,64(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(72) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#endif /* PLAT_ppc32_aix5 */ - -/* ------------------------ ppc64-aix5 ------------------------- */ - -#if defined(PLAT_ppc64_aix5) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "r0", "r2", "r3", \ - "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13" - -/* Expand the stack frame, copying enough info that unwinding - still works. Trashes r3. */ - -#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ - "addi 1,1,-" #_n_fr \ - "\n\t" \ - "ld 3," #_n_fr \ - "(1)\n\t" \ - "std 3,0(1)\n\t" - -#define VG_CONTRACT_FRAME_BY(_n_fr) "addi 1,1," #_n_fr "\n\t" - -/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned - long) == 8. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1, arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(128) \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(128) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - _argvec[2 + 10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(128) \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(128) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - _argvec[2 + 10] = (unsigned long)arg10; \ - _argvec[2 + 11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(144) \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(144) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, \ - arg11, arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3 + 12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2 + 1] = (unsigned long)arg1; \ - _argvec[2 + 2] = (unsigned long)arg2; \ - _argvec[2 + 3] = (unsigned long)arg3; \ - _argvec[2 + 4] = (unsigned long)arg4; \ - _argvec[2 + 5] = (unsigned long)arg5; \ - _argvec[2 + 6] = (unsigned long)arg6; \ - _argvec[2 + 7] = (unsigned long)arg7; \ - _argvec[2 + 8] = (unsigned long)arg8; \ - _argvec[2 + 9] = (unsigned long)arg9; \ - _argvec[2 + 10] = (unsigned long)arg10; \ - _argvec[2 + 11] = (unsigned long)arg11; \ - _argvec[2 + 12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(144) \ - /* arg12 */ \ - "ld 3,96(11)\n\t" \ - "std 3,136(1)\n\t" \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(144) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval))_res; \ - } while (0) - -#endif /* PLAT_ppc64_aix5 */ - -/* ------------------------------------------------------------------ */ -/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ -/* */ -/* ------------------------------------------------------------------ */ - -/* Some request codes. There are many more of these, but most are not - exposed to end-user view. These are the public ones, all of the - form 0x1000 + small_number. - - Core ones are in the range 0x00000000--0x0000ffff. The non-public - ones start at 0x2000. -*/ - -/* These macros are used by tools -- they must be public, but don't - embed them into other programs. */ -#define VG_USERREQ_TOOL_BASE(a, b) ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) -#define VG_IS_TOOL_USERREQ(a, b, v) (VG_USERREQ_TOOL_BASE(a, b) == ((v)&0xffff0000)) - -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! - This enum comprises an ABI exported by Valgrind to programs - which use client requests. DO NOT CHANGE THE ORDER OF THESE - ENTRIES, NOR DELETE ANY -- add new ones at the end. */ -typedef enum { - VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, - VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, - - /* These allow any function to be called from the simulated - CPU but run on the real CPU. Nb: the first arg passed to - the function is always the ThreadId of the running - thread! So CLIENT_CALL0 actually requires a 1 arg - function, etc. */ - VG_USERREQ__CLIENT_CALL0 = 0x1101, - VG_USERREQ__CLIENT_CALL1 = 0x1102, - VG_USERREQ__CLIENT_CALL2 = 0x1103, - VG_USERREQ__CLIENT_CALL3 = 0x1104, - - /* Can be useful in regression testing suites -- eg. can - send Valgrind's output to /dev/null and still count - errors. */ - VG_USERREQ__COUNT_ERRORS = 0x1201, - - /* These are useful and can be interpreted by any tool that - tracks malloc() et al, by using vg_replace_malloc.c. */ - VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, - VG_USERREQ__FREELIKE_BLOCK = 0x1302, - /* Memory pool support. */ - VG_USERREQ__CREATE_MEMPOOL = 0x1303, - VG_USERREQ__DESTROY_MEMPOOL = 0x1304, - VG_USERREQ__MEMPOOL_ALLOC = 0x1305, - VG_USERREQ__MEMPOOL_FREE = 0x1306, - VG_USERREQ__MEMPOOL_TRIM = 0x1307, - VG_USERREQ__MOVE_MEMPOOL = 0x1308, - VG_USERREQ__MEMPOOL_CHANGE = 0x1309, - VG_USERREQ__MEMPOOL_EXISTS = 0x130a, - - /* Allow printfs to valgrind log. */ - VG_USERREQ__PRINTF = 0x1401, - VG_USERREQ__PRINTF_BACKTRACE = 0x1402, - - /* Stack support. */ - VG_USERREQ__STACK_REGISTER = 0x1501, - VG_USERREQ__STACK_DEREGISTER = 0x1502, - VG_USERREQ__STACK_CHANGE = 0x1503 -} Vg_ClientRequest; - -#if !defined(__GNUC__) -#define __extension__ /* */ -#endif - -/* Returns the number of Valgrinds this code is running under. That - is, 0 if running natively, 1 if running under Valgrind, 2 if - running under Valgrind which is running under another Valgrind, - etc. */ -#define RUNNING_ON_VALGRIND \ - __extension__({ \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, VG_USERREQ__RUNNING_ON_VALGRIND, 0, \ - 0, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Discard translation of code in the range [_qzz_addr .. _qzz_addr + - _qzz_len - 1]. Useful if you are debugging a JITter or some such, - since it provides a way to make sure valgrind will retranslate the - invalidated area. Returns no value. */ -#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr, _qzz_len) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__DISCARD_TRANSLATIONS, _qzz_addr, \ - _qzz_len, 0, 0, 0); \ - } - -/* These requests are for getting Valgrind itself to print something. - Possibly with a backtrace. This is a really ugly hack. */ - -#if defined(NVALGRIND) - -#define VALGRIND_PRINTF(...) -#define VALGRIND_PRINTF_BACKTRACE(...) - -#else /* NVALGRIND */ - -/* Modern GCC will optimize the static routine out if unused, - and unused attribute will shut down warnings about it. */ -static int VALGRIND_PRINTF(const char* format, ...) - __attribute__((format(__printf__, 1, 2), __unused__)); -static int VALGRIND_PRINTF(const char* format, ...) { - unsigned long _qzz_res; - va_list vargs; - va_start(vargs, format); - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF, (unsigned long)format, - (unsigned long)vargs, 0, 0, 0); - va_end(vargs); - return (int)_qzz_res; -} - -static int VALGRIND_PRINTF_BACKTRACE(const char* format, ...) - __attribute__((format(__printf__, 1, 2), __unused__)); -static int VALGRIND_PRINTF_BACKTRACE(const char* format, ...) { - unsigned long _qzz_res; - va_list vargs; - va_start(vargs, format); - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE, (unsigned long)format, - (unsigned long)vargs, 0, 0, 0); - va_end(vargs); - return (int)_qzz_res; -} - -#endif /* NVALGRIND */ - -/* These requests allow control to move from the simulated CPU to the - real CPU, calling an arbitary function. - - Note that the current ThreadId is inserted as the first argument. - So this call: - - VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) - - requires f to have this signature: - - Word f(Word tid, Word arg1, Word arg2) - - where "Word" is a word-sized type. - - Note that these client requests are not entirely reliable. For example, - if you call a function with them that subsequently calls printf(), - there's a high chance Valgrind will crash. Generally, your prospects of - these working are made higher if the called function does not refer to - any global variables, and does not refer to any libc or other functions - (printf et al). Any kind of entanglement with libc or dynamic linking is - likely to have a bad outcome, for tricky reasons which we've grappled - with a lot in the past. -*/ -#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ - __extension__({ \ - unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, VG_USERREQ__CLIENT_CALL0, \ - _qyy_fn, 0, 0, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ - __extension__({ \ - unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, VG_USERREQ__CLIENT_CALL1, \ - _qyy_fn, _qyy_arg1, 0, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ - __extension__({ \ - unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, VG_USERREQ__CLIENT_CALL2, \ - _qyy_fn, _qyy_arg1, _qyy_arg2, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ - __extension__({ \ - unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, VG_USERREQ__CLIENT_CALL3, \ - _qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3, 0); \ - _qyy_res; \ - }) - -/* Counts the number of errors that have been recorded by a tool. Nb: - the tool must record the errors with VG_(maybe_record_error)() or - VG_(unique_error)() for them to be counted. */ -#define VALGRIND_COUNT_ERRORS \ - __extension__({ \ - unsigned int _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, VG_USERREQ__COUNT_ERRORS, 0, \ - 0, 0, 0, 0); \ - _qyy_res; \ - }) - -/* Mark a block of memory as having been allocated by a malloc()-like - function. `addr' is the start of the usable block (ie. after any - redzone) `rzB' is redzone size if the allocator can apply redzones; - use '0' if not. Adding redzones makes it more likely Valgrind will spot - block overruns. `is_zeroed' indicates if the memory is zeroed, as it is - for calloc(). Put it immediately after the point where a block is - allocated. - - If you're using Memcheck: If you're allocating memory via superblocks, - and then handing out small chunks of each superblock, if you don't have - redzones on your small blocks, it's worth marking the superblock with - VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are - detected. But if you can put redzones on, it's probably better to not do - this, so that messages for small overruns are described in terms of the - small block rather than the superblock (but if you have a big overrun - that skips over a redzone, you could miss an error this way). See - memcheck/tests/custom_alloc.c for an example. - - WARNING: if your allocator uses malloc() or 'new' to allocate - superblocks, rather than mmap() or brk(), this will not work properly -- - you'll likely get assertion failures during leak detection. This is - because Valgrind doesn't like seeing overlapping heap blocks. Sorry. - - Nb: block must be freed via a free()-like function specified - with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */ -#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__MALLOCLIKE_BLOCK, addr, sizeB, rzB, \ - is_zeroed, 0); \ - } - -/* Mark a block of memory as having been freed by a free()-like function. - `rzB' is redzone size; it must match that given to - VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak - checker. Put it immediately after the point where the block is freed. */ -#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__FREELIKE_BLOCK, addr, rzB, 0, 0, 0); \ - } - -/* Create a memory pool. */ -#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__CREATE_MEMPOOL, pool, rzB, is_zeroed, \ - 0, 0); \ - } - -/* Destroy a memory pool. */ -#define VALGRIND_DESTROY_MEMPOOL(pool) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__DESTROY_MEMPOOL, pool, 0, 0, 0, 0); \ - } - -/* Associate a piece of memory with a memory pool. */ -#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__MEMPOOL_ALLOC, pool, addr, size, 0, \ - 0); \ - } - -/* Disassociate a piece of memory from a memory pool. */ -#define VALGRIND_MEMPOOL_FREE(pool, addr) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__MEMPOOL_FREE, pool, addr, 0, 0, 0); \ - } - -/* Disassociate any pieces outside a particular range. */ -#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__MEMPOOL_TRIM, pool, addr, size, 0, 0); \ - } - -/* Resize and/or move a piece associated with a memory pool. */ -#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__MOVE_MEMPOOL, poolA, poolB, 0, 0, 0); \ - } - -/* Resize and/or move a piece associated with a memory pool. */ -#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__MEMPOOL_CHANGE, pool, addrA, addrB, \ - size, 0); \ - } - -/* Return 1 if a mempool exists, else 0. */ -#define VALGRIND_MEMPOOL_EXISTS(pool) \ - ({ \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__MEMPOOL_EXISTS, pool, 0, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Mark a piece of memory as being a stack. Returns a stack id. */ -#define VALGRIND_STACK_REGISTER(start, end) \ - ({ \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__STACK_REGISTER, start, end, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Unmark the piece of memory associated with a stack id as being a - stack. */ -#define VALGRIND_STACK_DEREGISTER(id) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__STACK_DEREGISTER, id, 0, 0, 0, 0); \ - } - -/* Change the start and end address of the stack id. */ -#define VALGRIND_STACK_CHANGE(id, start, end) \ - { \ - unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__STACK_CHANGE, id, start, end, 0, 0); \ - } - -#undef PLAT_x86_linux -#undef PLAT_amd64_linux -#undef PLAT_ppc32_linux -#undef PLAT_ppc64_linux -#undef PLAT_ppc32_aix5 -#undef PLAT_ppc64_aix5 - -#endif /* __VALGRIND_H */ diff --git a/be/src/http/action/check_rpc_channel_action.cpp b/be/src/http/action/check_rpc_channel_action.cpp index 61702dc932..8a1e81e6c7 100644 --- a/be/src/http/action/check_rpc_channel_action.cpp +++ b/be/src/http/action/check_rpc_channel_action.cpp @@ -64,8 +64,8 @@ void CheckRPCChannelAction::handle(HttpRequest* req) { return; } } catch (const std::exception& e) { - std::string err = fmt::format("invalid argument. port:{0}, payload_size: {1}", req_port, - req_payload_size); + std::string err = fmt::format("invalid argument. port: {0}, payload_size: {1}, reason: {}", + req_port, req_payload_size, e.what()); LOG(WARNING) << err; HttpChannel::send_reply(req, HttpStatus::INTERNAL_SERVER_ERROR, err); return; diff --git a/be/src/http/action/stream_load.cpp b/be/src/http/action/stream_load.cpp index 0e59c4c7ac..fdf6f6eaca 100644 --- a/be/src/http/action/stream_load.cpp +++ b/be/src/http/action/stream_load.cpp @@ -334,7 +334,7 @@ Status StreamLoadAction::_on_header(HttpRequest* http_req, std::shared_ptrtimeout_second = std::stoi(http_req->header(HTTP_TIMEOUT)); } catch (const std::invalid_argument& e) { - return Status::InvalidArgument("Invalid timeout format"); + return Status::InvalidArgument("Invalid timeout format, {}", e.what()); } } if (!http_req->header(HTTP_COMMENT).empty()) { @@ -470,7 +470,7 @@ Status StreamLoadAction::_process_put(HttpRequest* http_req, try { request.__set_execMemLimit(std::stoll(http_req->header(HTTP_EXEC_MEM_LIMIT))); } catch (const std::invalid_argument& e) { - return Status::InvalidArgument("Invalid mem limit format"); + return Status::InvalidArgument("Invalid mem limit format, {}", e.what()); } } if (!http_req->header(HTTP_JSONPATHS).empty()) { @@ -527,7 +527,7 @@ Status StreamLoadAction::_process_put(HttpRequest* http_req, request.__set_send_batch_parallelism( std::stoi(http_req->header(HTTP_SEND_BATCH_PARALLELISM))); } catch (const std::invalid_argument& e) { - return Status::InvalidArgument("Invalid send_batch_parallelism format"); + return Status::InvalidArgument("Invalid send_batch_parallelism format, {}", e.what()); } } diff --git a/be/src/http/action/stream_load_2pc.cpp b/be/src/http/action/stream_load_2pc.cpp index ce3a8961b2..8eabf2a6d2 100644 --- a/be/src/http/action/stream_load_2pc.cpp +++ b/be/src/http/action/stream_load_2pc.cpp @@ -53,7 +53,8 @@ void StreamLoad2PCAction::handle(HttpRequest* req) { try { ctx->txn_id = std::stoull(req_txn_id); } catch (const std::exception& e) { - status = Status::InternalError("convert txn_id [{}] failed", req_txn_id); + status = Status::InternalError("convert txn_id [{}] failed, reason={}", req_txn_id, + e.what()); status_result = status.to_json(); HttpChannel::send_reply(req, HttpStatus::OK, status_result); return; diff --git a/be/src/http/action/tablets_distribution_action.cpp b/be/src/http/action/tablets_distribution_action.cpp index 95ece915a0..b6c88ae65f 100644 --- a/be/src/http/action/tablets_distribution_action.cpp +++ b/be/src/http/action/tablets_distribution_action.cpp @@ -59,8 +59,8 @@ void TabletsDistributionAction::handle(HttpRequest* req) { try { partition_id = std::stoull(req_partition_id); } catch (const std::exception& e) { - LOG(WARNING) << "invalid argument. partition_id:" << req_partition_id; - Status status = Status::InternalError("invalid argument: {}", req_partition_id); + Status status = Status::InternalError("invalid argument: {}, reason:{}", + req_partition_id, e.what()); std::string status_result = status.to_json(); HttpChannel::send_reply(req, HttpStatus::INTERNAL_SERVER_ERROR, status_result); return; diff --git a/be/src/io/fs/broker_file_reader.cpp b/be/src/io/fs/broker_file_reader.cpp index ffd4c5154e..c48433ba23 100644 --- a/be/src/io/fs/broker_file_reader.cpp +++ b/be/src/io/fs/broker_file_reader.cpp @@ -67,7 +67,7 @@ Status BrokerFileReader::close() { try { try { (*_client)->closeReader(response, request); - } catch (apache::thrift::transport::TTransportException& e) { + } catch (apache::thrift::transport::TTransportException&) { std::this_thread::sleep_for(std::chrono::seconds(1)); RETURN_IF_ERROR((*_client).reopen()); (*_client)->closeReader(response, request); diff --git a/be/src/io/fs/broker_file_system.cpp b/be/src/io/fs/broker_file_system.cpp index cf7f34a9df..cdef7eef38 100644 --- a/be/src/io/fs/broker_file_system.cpp +++ b/be/src/io/fs/broker_file_system.cpp @@ -121,7 +121,7 @@ Status BrokerFileSystem::open_file_internal(const Path& file, int64_t file_size, Status status; try { (*_client)->openReader(*response, request); - } catch (apache::thrift::transport::TTransportException& e) { + } catch (apache::thrift::transport::TTransportException&) { std::this_thread::sleep_for(std::chrono::seconds(1)); RETURN_IF_ERROR((*_client).reopen()); (*_client)->openReader(*response, request); @@ -156,7 +156,7 @@ Status BrokerFileSystem::delete_file_impl(const Path& file) { try { (*_client)->deletePath(del_rep, del_req); - } catch (apache::thrift::transport::TTransportException& e) { + } catch (apache::thrift::transport::TTransportException&) { RETURN_IF_ERROR((*_client).reopen()); (*_client)->deletePath(del_rep, del_req); } @@ -196,7 +196,7 @@ Status BrokerFileSystem::exists_impl(const Path& path, bool* res) const { try { (*_client)->checkPathExist(check_rep, check_req); - } catch (apache::thrift::transport::TTransportException& e) { + } catch (apache::thrift::transport::TTransportException&) { RETURN_IF_ERROR((*_client).reopen()); (*_client)->checkPathExist(check_rep, check_req); } @@ -228,7 +228,7 @@ Status BrokerFileSystem::file_size_impl(const Path& path, int64_t* file_size) co TBrokerFileSizeResponse resp; try { (*_client)->fileSize(resp, req); - } catch (apache::thrift::transport::TTransportException& e) { + } catch (apache::thrift::transport::TTransportException&) { RETURN_IF_ERROR((*_client).reopen()); (*_client)->fileSize(resp, req); } @@ -269,7 +269,7 @@ Status BrokerFileSystem::list_impl(const Path& dir, bool only_file, std::vector< try { (*_client)->listPath(list_rep, list_req); - } catch (apache::thrift::transport::TTransportException& e) { + } catch (apache::thrift::transport::TTransportException&) { RETURN_IF_ERROR((*_client).reopen()); (*_client)->listPath(list_rep, list_req); } @@ -319,7 +319,7 @@ Status BrokerFileSystem::rename_impl(const Path& orig_name, const Path& new_name try { (*_client)->renamePath(op_status, rename_req); - } catch (apache::thrift::transport::TTransportException& e) { + } catch (apache::thrift::transport::TTransportException&) { RETURN_IF_ERROR((*_client).reopen()); (*_client)->renamePath(op_status, rename_req); } diff --git a/be/src/io/fs/broker_file_writer.cpp b/be/src/io/fs/broker_file_writer.cpp index ac34f381d3..8d237a4026 100644 --- a/be/src/io/fs/broker_file_writer.cpp +++ b/be/src/io/fs/broker_file_writer.cpp @@ -183,7 +183,7 @@ Status BrokerFileWriter::_open() { try { client->openWriter(response, request); - } catch (apache::thrift::transport::TTransportException& e) { + } catch (apache::thrift::transport::TTransportException&) { RETURN_IF_ERROR(client.reopen()); client->openWriter(response, request); } @@ -237,7 +237,7 @@ Status BrokerFileWriter::_write(const uint8_t* buf, size_t buf_len, size_t* writ try { client->pwrite(response, request); - } catch (apache::thrift::transport::TTransportException& e) { + } catch (apache::thrift::transport::TTransportException&) { RETURN_IF_ERROR(client.reopen()); // broker server will check write offset, so it is safe to re-try client->pwrite(response, request); diff --git a/be/src/olap/base_compaction.cpp b/be/src/olap/base_compaction.cpp index 883ede79a1..d7b186e230 100644 --- a/be/src/olap/base_compaction.cpp +++ b/be/src/olap/base_compaction.cpp @@ -52,11 +52,9 @@ Status BaseCompaction::prepare_compact() { LOG(WARNING) << "another base compaction is running. tablet=" << _tablet->full_name(); return Status::Error(); } - TRACE("got base compaction lock"); // 1. pick rowsets to compact RETURN_IF_ERROR(pick_rowsets_to_compact()); - TRACE("rowsets picked"); TRACE_COUNTER_INCREMENT("input_rowsets_count", _input_rowsets.size()); _tablet->set_clone_occurred(false); @@ -74,7 +72,6 @@ Status BaseCompaction::execute_compact_impl() { LOG(WARNING) << "another base compaction is running. tablet=" << _tablet->full_name(); return Status::Error(); } - TRACE("got base compaction lock"); // Clone task may happen after compaction task is submitted to thread pool, and rowsets picked // for compaction may change. In this case, current compaction task should not be executed. @@ -88,7 +85,6 @@ Status BaseCompaction::execute_compact_impl() { // 2. do base compaction, merge rowsets int64_t permits = get_compaction_permits(); RETURN_IF_ERROR(do_compaction(permits)); - TRACE("compaction finished"); // 3. set state to success _state = CompactionState::SUCCESS; @@ -96,7 +92,6 @@ Status BaseCompaction::execute_compact_impl() { // 4. add metric to base compaction DorisMetrics::instance()->base_compaction_deltas_total->increment(_input_rowsets.size()); DorisMetrics::instance()->base_compaction_bytes_total->increment(_input_rowsets_size); - TRACE("save base compaction metrics"); return Status::OK(); } diff --git a/be/src/olap/compaction.cpp b/be/src/olap/compaction.cpp index 0b1a702654..f174908824 100644 --- a/be/src/olap/compaction.cpp +++ b/be/src/olap/compaction.cpp @@ -86,7 +86,6 @@ Status Compaction::execute_compact() { } Status Compaction::do_compaction(int64_t permits) { - TRACE("start to do compaction"); uint32_t checksum_before; uint32_t checksum_after; if (config::enable_compaction_checksum) { @@ -270,7 +269,6 @@ Status Compaction::do_compaction_impl(int64_t permits) { if (handle_ordered_data_compaction()) { RETURN_IF_ERROR(modify_rowsets()); - TRACE("modify rowsets finished"); int64_t now = UnixMillis(); if (compaction_type() == ReaderType::READER_CUMULATIVE_COMPACTION) { @@ -300,7 +298,6 @@ Status Compaction::do_compaction_impl(int64_t permits) { if (compaction_type() == ReaderType::READER_COLD_DATA_COMPACTION) { Tablet::add_pending_remote_rowset(_output_rs_writer->rowset_id().to_string()); } - TRACE("prepare finished"); // 2. write merged rows to output rowset // The test results show that merger is low-memory-footprint, there is no need to tracker its mem pool @@ -328,7 +325,6 @@ Status Compaction::do_compaction_impl(int64_t permits) { << ", output_version=" << _output_version; return res; } - TRACE("merge rowsets finished"); TRACE_COUNTER_INCREMENT("merged_rows", stats.merged_rows); TRACE_COUNTER_INCREMENT("filtered_rows", stats.filtered_rows); @@ -342,11 +338,9 @@ Status Compaction::do_compaction_impl(int64_t permits) { TRACE_COUNTER_INCREMENT("output_rowset_data_size", _output_rowset->data_disk_size()); TRACE_COUNTER_INCREMENT("output_row_num", _output_rowset->num_rows()); TRACE_COUNTER_INCREMENT("output_segments_num", _output_rowset->num_segments()); - TRACE("output rowset built"); // 3. check correctness RETURN_IF_ERROR(check_correctness(stats)); - TRACE("check correctness finished"); if (_input_row_num > 0 && stats.rowid_conversion && config::inverted_index_compaction_enable) { OlapStopWatch inverted_watch; @@ -414,7 +408,6 @@ Status Compaction::do_compaction_impl(int64_t permits) { // 4. modify rowsets in memory RETURN_IF_ERROR(modify_rowsets(&stats)); - TRACE("modify rowsets finished"); // 5. update last success compaction time int64_t now = UnixMillis(); diff --git a/be/src/olap/cumulative_compaction.cpp b/be/src/olap/cumulative_compaction.cpp index 3c7d627194..9c4f5bae91 100644 --- a/be/src/olap/cumulative_compaction.cpp +++ b/be/src/olap/cumulative_compaction.cpp @@ -52,17 +52,14 @@ Status CumulativeCompaction::prepare_compact() { LOG(INFO) << "The tablet is under cumulative compaction. tablet=" << _tablet->full_name(); return Status::Error(); } - TRACE("got cumulative compaction lock"); // 1. calculate cumulative point _tablet->calculate_cumulative_point(); - TRACE("calculated cumulative point"); VLOG_CRITICAL << "after calculate, current cumulative point is " << _tablet->cumulative_layer_point() << ", tablet=" << _tablet->full_name(); // 2. pick rowsets to compact RETURN_IF_ERROR(pick_rowsets_to_compact()); - TRACE("rowsets picked"); TRACE_COUNTER_INCREMENT("input_rowsets_count", _input_rowsets.size()); _tablet->set_clone_occurred(false); @@ -75,7 +72,6 @@ Status CumulativeCompaction::execute_compact_impl() { LOG(INFO) << "The tablet is under cumulative compaction. tablet=" << _tablet->full_name(); return Status::Error(); } - TRACE("got cumulative compaction lock"); // Clone task may happen after compaction task is submitted to thread pool, and rowsets picked // for compaction may change. In this case, current compaction task should not be executed. @@ -89,7 +85,6 @@ Status CumulativeCompaction::execute_compact_impl() { // 3. do cumulative compaction, merge rowsets int64_t permits = get_compaction_permits(); RETURN_IF_ERROR(do_compaction(permits)); - TRACE("compaction finished"); // 4. set state to success _state = CompactionState::SUCCESS; @@ -103,7 +98,6 @@ Status CumulativeCompaction::execute_compact_impl() { // 6. add metric to cumulative compaction DorisMetrics::instance()->cumulative_compaction_deltas_total->increment(_input_rowsets.size()); DorisMetrics::instance()->cumulative_compaction_bytes_total->increment(_input_rowsets_size); - TRACE("save cumulative compaction metrics"); return Status::OK(); } diff --git a/be/src/olap/single_replica_compaction.cpp b/be/src/olap/single_replica_compaction.cpp index d19174da7a..78e9b79514 100644 --- a/be/src/olap/single_replica_compaction.cpp +++ b/be/src/olap/single_replica_compaction.cpp @@ -62,17 +62,14 @@ Status SingleReplicaCompaction::prepare_compact() { LOG(INFO) << "The tablet is under cumulative compaction. tablet=" << _tablet->full_name(); return Status::Error(); } - TRACE("got cumulative compaction lock"); std::unique_lock lock_base(_tablet->get_base_compaction_lock(), std::try_to_lock); if (!lock_base.owns_lock()) { LOG(WARNING) << "another base compaction is running. tablet=" << _tablet->full_name(); return Status::Error(); } - TRACE("got base compaction lock"); // 1. pick rowsets to compact RETURN_IF_ERROR(pick_rowsets_to_compact()); - TRACE("rowsets picked"); _tablet->set_clone_occurred(false); if (_input_rowsets.size() == 1) { return Status::Error(); @@ -101,14 +98,12 @@ Status SingleReplicaCompaction::execute_compact_impl() { LOG(INFO) << "The tablet is under cumulative compaction. tablet=" << _tablet->full_name(); return Status::Error(); } - TRACE("got cumulative compaction lock"); std::unique_lock lock_base(_tablet->get_base_compaction_lock(), std::try_to_lock); if (!lock_base.owns_lock()) { LOG(WARNING) << "another base compaction is running. tablet=" << _tablet->full_name(); return Status::Error(); } - TRACE("got base compaction lock"); // Clone task may happen after compaction task is submitted to thread pool, and rowsets picked // for compaction may change. In this case, current compaction task should not be executed. @@ -121,7 +116,6 @@ Status SingleReplicaCompaction::execute_compact_impl() { // 2. do single replica compaction RETURN_IF_ERROR(_do_single_replica_compaction()); - TRACE("single replica compaction finished"); // 3. set state to success _state = CompactionState::SUCCESS; @@ -130,8 +124,6 @@ Status SingleReplicaCompaction::execute_compact_impl() { } Status SingleReplicaCompaction::_do_single_replica_compaction() { - TRACE("start to do single replica compaction"); - _tablet->data_dir()->disks_compaction_num_increment(1); Status st = _do_single_replica_compaction_impl(); _tablet->data_dir()->disks_compaction_num_increment(-1); @@ -163,7 +155,6 @@ Status SingleReplicaCompaction::_do_single_replica_compaction_impl() { RETURN_IF_ERROR(_fetch_rowset(addr, token, proper_version)); // 5. modify rowsets in memory RETURN_IF_ERROR(modify_rowsets()); - TRACE("modify rowsets finished"); // 6. update last success compaction time if (compaction_type() == ReaderType::READER_CUMULATIVE_COMPACTION) { diff --git a/be/src/olap/storage_engine.cpp b/be/src/olap/storage_engine.cpp index f6cb05bc97..1d65da4d59 100644 --- a/be/src/olap/storage_engine.cpp +++ b/be/src/olap/storage_engine.cpp @@ -1055,7 +1055,6 @@ Status StorageEngine::create_tablet(const TCreateTabletReq& request) { LOG(WARNING) << "there is no available disk that can be used to create tablet."; return Status::Error(); } - TRACE("got data directory for create tablet"); return _tablet_manager->create_tablet(request, stores); } diff --git a/be/src/olap/tablet.cpp b/be/src/olap/tablet.cpp index 170041d268..c5bc5b85ec 100644 --- a/be/src/olap/tablet.cpp +++ b/be/src/olap/tablet.cpp @@ -1660,7 +1660,6 @@ Status Tablet::prepare_compaction_and_calculate_permits(CompactionType compactio }); ADOPT_TRACE(trace.get()); - TRACE("create cumulative compaction"); StorageEngine::instance()->create_cumulative_compaction(tablet, _cumulative_compaction); DorisMetrics::instance()->cumulative_compaction_request_total->increment(1); Status res = _cumulative_compaction->prepare_compact(); @@ -1689,7 +1688,6 @@ Status Tablet::prepare_compaction_and_calculate_permits(CompactionType compactio }); ADOPT_TRACE(trace.get()); - TRACE("create base compaction"); StorageEngine::instance()->create_base_compaction(tablet, _base_compaction); DorisMetrics::instance()->base_compaction_request_total->increment(1); Status res = _base_compaction->prepare_compact(); @@ -1718,7 +1716,6 @@ Status Tablet::prepare_single_replica_compaction(TabletSharedPtr tablet, CompactionType compaction_type) { scoped_refptr trace(new Trace); ADOPT_TRACE(trace.get()); - TRACE("create single replica compaction"); StorageEngine::instance()->create_single_replica_compaction(tablet, _single_replica_compaction, compaction_type); @@ -1734,7 +1731,6 @@ Status Tablet::prepare_single_replica_compaction(TabletSharedPtr tablet, void Tablet::execute_single_replica_compaction(CompactionType compaction_type) { scoped_refptr trace(new Trace); ADOPT_TRACE(trace.get()); - TRACE("execute single replica compaction"); Status res = _single_replica_compaction->execute_compact(); if (!res.ok()) { if (compaction_type == CompactionType::CUMULATIVE_COMPACTION) { @@ -1783,7 +1779,6 @@ void Tablet::execute_compaction(CompactionType compaction_type) { }); ADOPT_TRACE(trace.get()); - TRACE("execute cumulative compaction"); Status res = _cumulative_compaction->execute_compact(); if (!res.ok()) { set_last_cumu_compaction_failure_time(UnixMillis()); @@ -1806,7 +1801,6 @@ void Tablet::execute_compaction(CompactionType compaction_type) { }); ADOPT_TRACE(trace.get()); - TRACE("create base compaction"); Status res = _base_compaction->execute_compact(); if (!res.ok()) { set_last_base_compaction_failure_time(UnixMillis()); diff --git a/be/src/olap/tablet_manager.cpp b/be/src/olap/tablet_manager.cpp index f0494dd3ab..aa66a4c480 100644 --- a/be/src/olap/tablet_manager.cpp +++ b/be/src/olap/tablet_manager.cpp @@ -247,7 +247,6 @@ Status TabletManager::create_tablet(const TCreateTabletReq& request, std::vector LOG(INFO) << "begin to create tablet. tablet_id=" << tablet_id; std::lock_guard wrlock(_get_tablets_shard_lock(tablet_id)); - TRACE("got tablets shard lock"); // Make create_tablet operation to be idempotent: // 1. Return true if tablet with same tablet_id and schema_hash exist; // false if tablet with same tablet_id but different schema_hash exist. @@ -290,7 +289,6 @@ Status TabletManager::create_tablet(const TCreateTabletReq& request, std::vector DorisMetrics::instance()->create_tablet_requests_failed->increment(1); return Status::Error(); } - TRACE("succeed to create tablet"); LOG(INFO) << "success to create tablet. tablet_id=" << tablet_id; return Status::OK(); @@ -364,7 +362,6 @@ TabletSharedPtr TabletManager::_internal_create_tablet_unlocked( LOG(WARNING) << "fail to get tablet. res=" << res; break; } - TRACE("add tablet to StorageEngine"); } while (0); if (res.ok()) { diff --git a/be/src/runtime/broker_mgr.cpp b/be/src/runtime/broker_mgr.cpp index 6102da5e40..6d17f32ffb 100644 --- a/be/src/runtime/broker_mgr.cpp +++ b/be/src/runtime/broker_mgr.cpp @@ -95,7 +95,7 @@ void BrokerMgr::ping(const TNetworkAddress& addr) { status = client.reopen(); if (!status.ok()) { LOG(WARNING) << "Create broker client failed. broker=" << addr - << ", status=" << status; + << ", status=" << status << ", reason=" << e.what(); return; } client->ping(response, request); diff --git a/be/src/runtime/thread_context.h b/be/src/runtime/thread_context.h index 4fbfd9155d..80178a8b68 100644 --- a/be/src/runtime/thread_context.h +++ b/be/src/runtime/thread_context.h @@ -62,8 +62,10 @@ // And count the memory during thread execution (is actually also the code segment that executes the function) // to specify MemTrackerLimiter, and expect to handle when the memory exceeds the limit, for example cancel query. // Usage is similar to SCOPED_CONSUME_MEM_TRACKER. -#define SCOPED_ATTACH_TASK(arg1, ...) \ - auto VARNAME_LINENUM(attach_task) = AttachTask(arg1, ##__VA_ARGS__) +#define SCOPED_ATTACH_TASK(arg1) auto VARNAME_LINENUM(attach_task) = AttachTask(arg1) + +#define SCOPED_ATTACH_TASK_WITH_ID(arg1, arg2, arg3) \ + auto VARNAME_LINENUM(attach_task) = AttachTask(arg1, arg2, arg3) // Switch MemTrackerLimiter for count memory during thread execution. // Usually used after SCOPED_ATTACH_TASK, in order to count the memory of the specified code segment into another @@ -72,6 +74,7 @@ auto VARNAME_LINENUM(switch_mem_tracker) = SwitchThreadMemTrackerLimiter(mem_tracker_limiter) #else #define SCOPED_ATTACH_TASK(arg1, ...) (void)0 +#define SCOPED_ATTACH_TASK_WITH_ID(arg1, arg2, arg3) (void)0 #define SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(mem_tracker_limiter) (void)0 #endif diff --git a/be/src/util/cidr.cpp b/be/src/util/cidr.cpp index 573074bae1..ec2a4aeb3c 100644 --- a/be/src/util/cidr.cpp +++ b/be/src/util/cidr.cpp @@ -59,7 +59,7 @@ bool CIDR::reset(const std::string& cidr_str) { try { len = std::stoi(suffix, &pos); } catch (const std::exception& e) { - LOG(WARNING) << "Wrong CIDR format. network=" << cidr_str; + LOG(WARNING) << "Wrong CIDR format. network=" << cidr_str << ", reason=" << e.what(); return false; } diff --git a/be/src/util/hash_util.hpp b/be/src/util/hash_util.hpp index 60fffd9466..355303087c 100644 --- a/be/src/util/hash_util.hpp +++ b/be/src/util/hash_util.hpp @@ -330,6 +330,10 @@ public: seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wused-but-marked-unused" +#endif // xxHash function for a byte array. For convenience, a 64-bit seed is also // hashed into the result. The mapping may change from time to time. static xxh_u64 xxHash64WithSeed(const char* s, size_t len, xxh_u64 seed) { @@ -341,6 +345,9 @@ public: static const int INT_VALUE = 0; return XXH3_64bits_withSeed(reinterpret_cast(&INT_VALUE), sizeof(int), seed); } +#if defined(__clang__) +#pragma clang diagnostic pop +#endif }; } // namespace doris diff --git a/be/src/util/trace.h b/be/src/util/trace.h index 7fe40a2aa2..ea1f3e665c 100644 --- a/be/src/util/trace.h +++ b/be/src/util/trace.h @@ -47,22 +47,6 @@ class Trace; // 't' should be a Trace* pointer. #define ADOPT_TRACE(t) doris::ScopedAdoptTrace _adopt_trace(t); -// Issue a trace message, if tracing is enabled in the current thread. -// See Trace::SubstituteAndTrace for arguments. -// Example: -// TRACE("Acquired timestamp $0", timestamp); -#define TRACE(format, substitutions...) \ - do { \ - doris::Trace* _trace = doris::Trace::CurrentTrace(); \ - if (_trace) { \ - _trace->SubstituteAndTrace(__FILE__, __LINE__, (format), ##substitutions); \ - } \ - } while (0) - -// Like the above, but takes the trace pointer as an explicit argument. -#define TRACE_TO(trace, format, substitutions...) \ - (trace)->SubstituteAndTrace(__FILE__, __LINE__, (format), ##substitutions) - // Increment a counter associated with the current trace. // // Each trace contains a map of counters which can be used to keep @@ -101,21 +85,6 @@ class Trace; #define TRACE_COUNTER_SCOPE_LATENCY_US(counter_name) \ ::doris::ScopedTraceLatencyCounter _scoped_latency(counter_name) -// Construct a constant C string counter name which acts as a sort of -// coarse-grained histogram for trace metrics. -#define BUCKETED_COUNTER_NAME(prefix, duration_us) \ - []() { \ - if (duration_us >= 100 * 1000) { \ - return prefix "_gt_100_ms"; \ - } else if (duration_us >= 10 * 1000) { \ - return prefix "_10-100_ms"; \ - } else if (duration_us >= 1000) { \ - return prefix "_1-10_ms"; \ - } else { \ - return prefix "_lt_1ms"; \ - } \ - }() - // If this scope times out, make a simple trace. // It will log the cost time only. // Timeout is chrono duration struct, eg: 5ms, 100 * 1s. diff --git a/be/src/vec/aggregate_functions/aggregate_function_java_udaf.h b/be/src/vec/aggregate_functions/aggregate_function_java_udaf.h index 478e7d79c2..b51aed7849 100644 --- a/be/src/vec/aggregate_functions/aggregate_function_java_udaf.h +++ b/be/src/vec/aggregate_functions/aggregate_function_java_udaf.h @@ -270,8 +270,8 @@ public: } catch (std::bad_alloc const& e) { \ throw doris::Exception( \ ErrorCode::INTERNAL_ERROR, \ - "memory allocate failed in column string, buffer:{},size:{}", \ - increase_buffer_size, buffer_size); \ + "memory allocate failed in column string, buffer:{},size:{},reason:{}", \ + increase_buffer_size, buffer_size, e.what()); \ } \ *output_value_buffer = reinterpret_cast(chars.data()); \ *output_intermediate_state_ptr = chars.size(); \ @@ -317,10 +317,10 @@ public: chars.resize(buffer_size); \ offsets.resize(buffer_size); \ } catch (std::bad_alloc const& e) { \ - throw doris::Exception( \ - ErrorCode::INTERNAL_ERROR, \ - "memory allocate failed in array column string, buffer:{},size:{}", \ - increase_buffer_size, buffer_size); \ + throw doris::Exception(ErrorCode::INTERNAL_ERROR, \ + "memory allocate failed in array column string, " \ + "buffer:{},size:{},reason:{}", \ + increase_buffer_size, buffer_size, e.what()); \ } \ *output_array_null_ptr = reinterpret_cast(null_map_data.data()); \ *output_value_buffer = reinterpret_cast(chars.data()); \ @@ -342,10 +342,10 @@ public: null_map_data.resize(buffer_size); \ data_column->resize(buffer_size); \ } catch (std::bad_alloc const& e) { \ - throw doris::Exception( \ - ErrorCode::INTERNAL_ERROR, \ - "memory allocate failed in array number column, buffer:{},size:{}", \ - increase_buffer_size, buffer_size); \ + throw doris::Exception(ErrorCode::INTERNAL_ERROR, \ + "memory allocate failed in array number column, " \ + "buffer:{},size:{},reason:{}", \ + increase_buffer_size, buffer_size, e.what()); \ } \ *output_array_null_ptr = reinterpret_cast(null_map_data.data()); \ *output_value_buffer = \ diff --git a/be/src/vec/runtime/vdata_stream_recvr.cpp b/be/src/vec/runtime/vdata_stream_recvr.cpp index a59ac3c7fc..c65a669f9b 100644 --- a/be/src/vec/runtime/vdata_stream_recvr.cpp +++ b/be/src/vec/runtime/vdata_stream_recvr.cpp @@ -360,7 +360,7 @@ Status VDataStreamRecvr::create_merger(const VExprContextSPtrs& ordering_expr, void VDataStreamRecvr::add_block(const PBlock& pblock, int sender_id, int be_number, int64_t packet_seq, ::google::protobuf::Closure** done) { - SCOPED_ATTACH_TASK(_query_mem_tracker, _query_id, _fragment_instance_id); + SCOPED_ATTACH_TASK_WITH_ID(_query_mem_tracker, _query_id, _fragment_instance_id); int use_sender_id = _is_merging ? sender_id : 0; _sender_queues[use_sender_id]->add_block(pblock, be_number, packet_seq, done); } diff --git a/be/test/CMakeLists.txt b/be/test/CMakeLists.txt index 055480f814..e98961f03a 100644 --- a/be/test/CMakeLists.txt +++ b/be/test/CMakeLists.txt @@ -202,7 +202,6 @@ set(UTIL_TEST_FILES util/thread_test.cpp util/threadpool_test.cpp util/mysql_row_buffer_test.cpp - util/trace_test.cpp util/easy_json-test.cpp util/http_channel_test.cpp util/histogram_test.cpp diff --git a/be/test/util/trace_test.cpp b/be/test/util/trace_test.cpp deleted file mode 100644 index 2cc477ac0c..0000000000 --- a/be/test/util/trace_test.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -#include "util/trace.h" - -#include -#include -#include - -#include -// IWYU pragma: no_include -#include // IWYU pragma: keep -#include -#include -#include -#include - -#include "gtest/gtest_pred_impl.h" -#include "gutil/ref_counted.h" -#include "util/trace_metrics.h" - -using rapidjson::Document; -using rapidjson::Value; -using std::string; -using std::thread; -using std::vector; - -namespace doris { - -class TraceTest : public ::testing::Test {}; - -// Replace all digits in 's' with the character 'X'. -static std::string XOutDigits(const string& s) { - std::string ret; - ret.reserve(s.size()); - for (char c : s) { - if (isdigit(c)) { - ret.push_back('X'); - } else { - ret.push_back(c); - } - } - return ret; -} - -TEST_F(TraceTest, TestBasic) { - scoped_refptr t(new Trace); - TRACE_TO(t, "hello $0, $1", "world", 12345); - TRACE_TO(t, "goodbye $0, $1", "cruel world", 54321); - - std::string result = XOutDigits(t->DumpToString(Trace::NO_FLAGS)); - EXPECT_EQ( - "XXXX XX:XX:XX.XXXXXX trace_test.cpp:XX] hello world, XXXXX\n" - "XXXX XX:XX:XX.XXXXXX trace_test.cpp:XX] goodbye cruel world, XXXXX\n", - result); -} - -TEST_F(TraceTest, TestAttach) { - scoped_refptr traceA(new Trace); - scoped_refptr traceB(new Trace); - { - ADOPT_TRACE(traceA.get()); - EXPECT_EQ(traceA.get(), Trace::CurrentTrace()); - { - ADOPT_TRACE(traceB.get()); - EXPECT_EQ(traceB.get(), Trace::CurrentTrace()); - TRACE("hello from traceB"); - } - EXPECT_EQ(traceA.get(), Trace::CurrentTrace()); - TRACE("hello from traceA"); - } - EXPECT_TRUE(Trace::CurrentTrace() == nullptr); - TRACE("this goes nowhere"); - - EXPECT_EQ("XXXX XX:XX:XX.XXXXXX trace_test.cpp:XX] hello from traceA\n", - XOutDigits(traceA->DumpToString(Trace::NO_FLAGS))); - EXPECT_EQ("XXXX XX:XX:XX.XXXXXX trace_test.cpp:XX] hello from traceB\n", - XOutDigits(traceB->DumpToString(Trace::NO_FLAGS))); -} - -TEST_F(TraceTest, TestChildTrace) { - scoped_refptr traceA(new Trace); - scoped_refptr traceB(new Trace); - ADOPT_TRACE(traceA.get()); - traceA->AddChildTrace("child", traceB.get()); - TRACE("hello from traceA"); - { - ADOPT_TRACE(traceB.get()); - TRACE("hello from traceB"); - } - EXPECT_EQ( - "XXXX XX:XX:XX.XXXXXX trace_test.cpp:XXX] hello from traceA\n" - "Related trace 'child':\n" - "XXXX XX:XX:XX.XXXXXX trace_test.cpp:XXX] hello from traceB\n", - XOutDigits(traceA->DumpToString(Trace::NO_FLAGS))); -} - -TEST_F(TraceTest, TestTraceMetrics) { - scoped_refptr trace(new Trace); - trace->metrics()->Increment("foo", 10); - trace->metrics()->Increment("bar", 10); - for (int i = 0; i < 1000; i++) { - trace->metrics()->Increment("baz", i); - } - EXPECT_EQ("{\"bar\":10,\"baz\":499500,\"foo\":10}", trace->MetricsAsJSON()); - - { - ADOPT_TRACE(trace.get()); - TRACE_COUNTER_SCOPE_LATENCY_US("test_scope_us"); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - auto m = trace->metrics()->Get(); - EXPECT_GE(m["test_scope_us"], 80 * 1000); -} - -} // namespace doris diff --git a/dist/LICENSE-dist.txt b/dist/LICENSE-dist.txt index 5501e9e567..93134e043b 100644 --- a/dist/LICENSE-dist.txt +++ b/dist/LICENSE-dist.txt @@ -252,46 +252,6 @@ be/src/gutil/utf/*: licensed under the following terms: -------------------------------------------------------------------------------- -be/src/gutil/valgrind.h: licensed under the following terms: - - This file is part of Valgrind, a dynamic binary instrumentation - framework. - - Copyright (C) 2000-2008 Julian Seward. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --------------------------------------------------------------------------------- - be/src/gutil: 3-clause BSD Except above files in this module, other files of this module are derived from code in