You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
9.4 KiB
172 lines
9.4 KiB
// Copyright 2017 The Fuchsia Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef SYSROOT_ZIRCON_SANITIZER_H_
|
|
#define SYSROOT_ZIRCON_SANITIZER_H_
|
|
|
|
// Interfaces declared in this file are intended for the use of sanitizer
|
|
// runtime library implementation code. Each sanitizer runtime works only
|
|
// with the appropriately sanitized build of libc. These functions should
|
|
// never be called when using the unsanitized libc. But these names are
|
|
// always exported so that the libc ABI is uniform across sanitized and
|
|
// unsanitized builds (only unsanitized shared library binaries are used at
|
|
// link time, including linking the sanitizer runtime shared libraries).
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <threads.h>
|
|
#include <zircon/compiler.h>
|
|
#include <zircon/types.h>
|
|
|
|
__BEGIN_CDECLS
|
|
|
|
// These are aliases for the functions defined in libc, which are always
|
|
// the unsanitized versions. The sanitizer runtimes can call them by these
|
|
// aliases when they are overriding libc's definitions of the unadorned
|
|
// symbols.
|
|
__typeof(memcpy) __unsanitized_memcpy;
|
|
__typeof(memmove) __unsanitized_memmove;
|
|
__typeof(memset) __unsanitized_memset;
|
|
|
|
// The sanitized libc allocates the shadow memory in the appropriate ratio for
|
|
// the particular sanitizer (shadow_base == shadow_limit >> SHADOW_SCALE)
|
|
// early during startup, before any other address space allocations can occur.
|
|
// Shadow memory always starts at address zero:
|
|
// [memory_limit, UINTPTR_MAX) Address space reserved by the system.
|
|
// [shadow_limit, memory_limit) Address space available to the user.
|
|
// [shadow_base, shadow_limit) Shadow memory, preallocated.
|
|
// [0, shadow_base) Shadow gap, cannot be allocated.
|
|
typedef struct saniziter_shadow_bounds {
|
|
uintptr_t shadow_base;
|
|
uintptr_t shadow_limit;
|
|
uintptr_t memory_limit;
|
|
} sanitizer_shadow_bounds_t;
|
|
|
|
// Returns the shadow bounds for the current process.
|
|
sanitizer_shadow_bounds_t __sanitizer_shadow_bounds(void);
|
|
|
|
// Fill the shadow memory corresponding to [base, base+size) with |value|. The
|
|
// threshold is used as a hint to determine when to switch to a more efficient
|
|
// mechanism when zero-filling large shadow regions. This assumes that both
|
|
// |base| and |size| are aligned to the shadow multiple.
|
|
void __sanitizer_fill_shadow(uintptr_t base, size_t size, uint8_t value, size_t threshold);
|
|
|
|
// Write logging information from the sanitizer runtime. The buffer
|
|
// is expected to be printable text with '\n' ending each line.
|
|
// Timestamps and globally unique identifiers of the calling process
|
|
// and thread (zx_koid_t) are attached to all messages, so there is no
|
|
// need to include those details in the text. The log of messages
|
|
// written with this call automatically includes address and ELF build
|
|
// ID details of the program and all shared libraries sufficient to
|
|
// translate raw address values into program symbols or source
|
|
// locations via a post-processor that has access to the original ELF
|
|
// files and their debugging information. The text can contain markup
|
|
// around address values that should be resolved symbolically; see
|
|
// TODO(mcgrathr) for the format and details of the post-processor.
|
|
void __sanitizer_log_write(const char* buffer, size_t len);
|
|
|
|
// Runtimes that have binary data to publish (e.g. coverage) use this
|
|
// interface. The name describes the data sink that will receive this
|
|
// blob of data; the string is not used after this call returns. The
|
|
// caller creates a VMO (e.g. zx_vmo_create) and passes it in; the VMO
|
|
// handle is consumed by this call. Each particular data sink has its
|
|
// own conventions about both the format of the data in the VMO and the
|
|
// protocol for when data must be written there. For some sinks, the
|
|
// VMO's data is used immediately. For other sinks, the caller is
|
|
// expected to have the VMO mapped in and be writing more data there
|
|
// throughout the life of the process, to be analyzed only after the
|
|
// process terminates. Yet others might use an asynchronous shared
|
|
// memory protocol between producer and consumer.
|
|
void __sanitizer_publish_data(const char* sink_name, zx_handle_t vmo);
|
|
|
|
// Runtimes that want to read configuration files use this interface.
|
|
// The name is a string from the user (something akin to a file name
|
|
// but not necessarily actually a file name); the string is not used
|
|
// after this call returns. On success, this yields a read-only VMO
|
|
// handle from which the contents associated with that name can be
|
|
// read; the caller is responsible for closing this handle.
|
|
zx_status_t __sanitizer_get_configuration(const char* config_name, zx_handle_t* out_vmo);
|
|
|
|
// Changes protection of the code in the range of len bytes starting
|
|
// from addr. The writable argument specifies whether the code should
|
|
// be made writable or not. This function is only valid on ranges within
|
|
// the caller's own code segment.
|
|
// TODO(phosek) removes this when the proper debugging interface exists.
|
|
zx_status_t __sanitizer_change_code_protection(uintptr_t addr, size_t len, bool writable);
|
|
|
|
// This stops all other threads in the process so memory should be quiescent.
|
|
// Then it makes callbacks for memory regions containing non-const global
|
|
// variables, thread stacks, thread registers, and thread-local storage
|
|
// regions (this includes thread_local variables as well as tss_set or
|
|
// pthread_setspecific values). Each callback is optional; no such callbacks
|
|
// are made if a null function pointer is given. The memory region passed to
|
|
// each callback can be accessed only during that single callback and might no
|
|
// longer be valid once the callback returns. Then it makes a final callback
|
|
// before allowing other threads to resume running normally. If there are
|
|
// problems stopping threads, no memory callbacks will be made and the
|
|
// argument to the final callback will get an error code rather than ZX_OK.
|
|
typedef void sanitizer_memory_snapshot_callback_t(void* mem, size_t len, void* arg);
|
|
void __sanitizer_memory_snapshot(sanitizer_memory_snapshot_callback_t* globals,
|
|
sanitizer_memory_snapshot_callback_t* stacks,
|
|
sanitizer_memory_snapshot_callback_t* regs,
|
|
sanitizer_memory_snapshot_callback_t* tls,
|
|
void (*done)(zx_status_t, void*), void* arg);
|
|
|
|
// The "hook" interfaces are functions that the sanitizer runtime library
|
|
// can define and libc will call. There are default definitions in libc
|
|
// which do nothing, but any other definitions will override those. These
|
|
// declarations use __EXPORT (i.e. explicit STV_DEFAULT) to ensure any user
|
|
// definitions are seen by libc even if the user code is being compiled
|
|
// with -fvisibility=hidden or equivalent.
|
|
|
|
// This is called at program startup, with the arguments that will be
|
|
// passed to main. This is called before any other application code,
|
|
// including both static constructors and initialization of things like
|
|
// fdio and zx_take_startup_handle. It's basically the first thing called
|
|
// after libc's most basic internal global initialization is complete and
|
|
// the initial thread has switched to its real thread stack. Since not
|
|
// even all of libc's own constructors have run yet, this should not call
|
|
// into libc or other library code.
|
|
__EXPORT void __sanitizer_startup_hook(int argc, char** argv, char** envp, void* stack_base,
|
|
size_t stack_size);
|
|
|
|
// This is called when a new thread has been created but is not yet
|
|
// running. Its C11 thrd_t value has been determined and its stack has
|
|
// been allocated. All that remains is to actually start the thread
|
|
// running (which can fail only in catastrophic bug situations). Its
|
|
// return value will be passed to __sanitizer_thread_create_hook, below.
|
|
__EXPORT void* __sanitizer_before_thread_create_hook(thrd_t thread, bool detached, const char* name,
|
|
void* stack_base, size_t stack_size);
|
|
|
|
// This is called after a new thread has been created or creation has
|
|
// failed at the final stage; __sanitizer_before_thread_create_hook has
|
|
// been called first, and its return value is the first argument here.
|
|
// The second argument is what the return value of C11 thrd_create would
|
|
// be for this creation attempt (which might have been instigated by
|
|
// either thrd_create or pthread_create). If it's thrd_success, then
|
|
// the new thread has now started running. Otherwise (it's a different
|
|
// <threads.h> thrd_* value), thread creation has failed and the thread
|
|
// details reported to __sanitizer_before_thread_create_hook will be
|
|
// freed without the thread ever starting.
|
|
__EXPORT void __sanitizer_thread_create_hook(void* hook, thrd_t thread, int error);
|
|
|
|
// This is called in each new thread as it starts up. The argument is
|
|
// the same one returned by __sanitizer_before_thread_create_hook and
|
|
// previously passed to __sanitizer_thread_create_hook.
|
|
__EXPORT void __sanitizer_thread_start_hook(void* hook, thrd_t self);
|
|
|
|
// This is called in each thread just before it dies.
|
|
// All thread-specific destructors have been run.
|
|
// The argument is the same one passed to __sanitizer_thread_start_hook.
|
|
__EXPORT void __sanitizer_thread_exit_hook(void* hook, thrd_t self);
|
|
|
|
// This is called with the argument to _exit and its return value
|
|
// is the actual exit status for the process.
|
|
__EXPORT int __sanitizer_process_exit_hook(int status);
|
|
|
|
__END_CDECLS
|
|
|
|
#endif // SYSROOT_ZIRCON_SANITIZER_H_
|