mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-30 01:04:36 +00:00
436 lines
14 KiB
C++
436 lines
14 KiB
C++
/* internal.h -- Internal header file for stack backtrace library.
|
|
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
|
Written by Ian Lance Taylor, Google.
|
|
|
|
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) 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.
|
|
|
|
(3) 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. */
|
|
|
|
#ifndef BACKTRACE_INTERNAL_H
|
|
#define BACKTRACE_INTERNAL_H
|
|
|
|
/* We assume that <sys/types.h> and "backtrace.h" have already been
|
|
included. */
|
|
|
|
#ifndef GCC_VERSION
|
|
# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
|
|
#endif
|
|
|
|
#if (GCC_VERSION < 2007)
|
|
# define __attribute__(x)
|
|
#endif
|
|
|
|
#ifndef ATTRIBUTE_UNUSED
|
|
# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
|
|
#endif
|
|
|
|
#ifndef ATTRIBUTE_MALLOC
|
|
# if (GCC_VERSION >= 2096)
|
|
# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
|
|
# else
|
|
# define ATTRIBUTE_MALLOC
|
|
# endif
|
|
#endif
|
|
|
|
#ifndef ATTRIBUTE_FALLTHROUGH
|
|
# if (GCC_VERSION >= 7000)
|
|
# define ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__))
|
|
# else
|
|
# define ATTRIBUTE_FALLTHROUGH
|
|
# endif
|
|
#endif
|
|
|
|
#ifndef HAVE_SYNC_FUNCTIONS
|
|
|
|
/* Define out the sync functions. These should never be called if
|
|
they are not available. */
|
|
|
|
#define __sync_bool_compare_and_swap(A, B, C) (abort(), 1)
|
|
#define __sync_lock_test_and_set(A, B) (abort(), 0)
|
|
#define __sync_lock_release(A) abort()
|
|
|
|
#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
|
|
|
|
#ifdef HAVE_ATOMIC_FUNCTIONS
|
|
|
|
/* We have the atomic builtin functions. */
|
|
|
|
#define backtrace_atomic_load_pointer(p) \
|
|
__atomic_load_n ((p), __ATOMIC_ACQUIRE)
|
|
#define backtrace_atomic_load_int(p) \
|
|
__atomic_load_n ((p), __ATOMIC_ACQUIRE)
|
|
#define backtrace_atomic_store_pointer(p, v) \
|
|
__atomic_store_n ((p), (v), __ATOMIC_RELEASE)
|
|
#define backtrace_atomic_store_size_t(p, v) \
|
|
__atomic_store_n ((p), (v), __ATOMIC_RELEASE)
|
|
#define backtrace_atomic_store_int(p, v) \
|
|
__atomic_store_n ((p), (v), __ATOMIC_RELEASE)
|
|
|
|
#else /* !defined (HAVE_ATOMIC_FUNCTIONS) */
|
|
#ifdef HAVE_SYNC_FUNCTIONS
|
|
|
|
/* We have the sync functions but not the atomic functions. Define
|
|
the atomic ones in terms of the sync ones. */
|
|
|
|
extern void *backtrace_atomic_load_pointer (void *);
|
|
extern int backtrace_atomic_load_int (int *);
|
|
extern void backtrace_atomic_store_pointer (void *, void *);
|
|
extern void backtrace_atomic_store_size_t (size_t *, size_t);
|
|
extern void backtrace_atomic_store_int (int *, int);
|
|
|
|
#else /* !defined (HAVE_SYNC_FUNCTIONS) */
|
|
|
|
/* We have neither the sync nor the atomic functions. These will
|
|
never be called. */
|
|
|
|
#define backtrace_atomic_load_pointer(p) (abort(), (void *) NULL)
|
|
#define backtrace_atomic_load_int(p) (abort(), 0)
|
|
#define backtrace_atomic_store_pointer(p, v) abort()
|
|
#define backtrace_atomic_store_size_t(p, v) abort()
|
|
#define backtrace_atomic_store_int(p, v) abort()
|
|
|
|
#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
|
|
#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */
|
|
|
|
namespace tracy
|
|
{
|
|
|
|
/* The type of the function that collects file/line information. This
|
|
is like backtrace_pcinfo. */
|
|
|
|
typedef int (*fileline) (struct backtrace_state *state, uintptr_t pc,
|
|
backtrace_full_callback callback,
|
|
backtrace_error_callback error_callback, void *data);
|
|
|
|
/* The type of the function that collects symbol information. This is
|
|
like backtrace_syminfo. */
|
|
|
|
typedef void (*syminfo) (struct backtrace_state *state, uintptr_t pc,
|
|
backtrace_syminfo_callback callback,
|
|
backtrace_error_callback error_callback, void *data);
|
|
|
|
/* The type of the function that will trigger an known address range refresh
|
|
(if pc passed in is for an address whichs lies ourtisde of known ranges) */
|
|
typedef int (*request_known_address_ranges_refresh)(struct backtrace_state *state,
|
|
uintptr_t pc);
|
|
|
|
/* What the backtrace state pointer points to. */
|
|
|
|
struct backtrace_state
|
|
{
|
|
/* The name of the executable. */
|
|
const char *filename;
|
|
/* Non-zero if threaded. */
|
|
int threaded;
|
|
/* The master lock for fileline_fn, fileline_data, syminfo_fn,
|
|
syminfo_data, fileline_initialization_failed and everything the
|
|
data pointers point to. */
|
|
void *lock;
|
|
/* The function that returns file/line information. */
|
|
fileline fileline_fn;
|
|
/* The data to pass to FILELINE_FN. */
|
|
void *fileline_data;
|
|
/* The function that returns symbol information. */
|
|
syminfo syminfo_fn;
|
|
/* The data to pass to SYMINFO_FN. */
|
|
void *syminfo_data;
|
|
/* Whether initializing the file/line information failed. */
|
|
int fileline_initialization_failed;
|
|
/* The lock for the freelist. */
|
|
int lock_alloc;
|
|
/* The freelist when using mmap. */
|
|
struct backtrace_freelist_struct *freelist;
|
|
/* Trigger an known address range refresh */
|
|
request_known_address_ranges_refresh request_known_address_ranges_refresh_fn;
|
|
};
|
|
|
|
/* Open a file for reading. Returns -1 on error. If DOES_NOT_EXIST
|
|
is not NULL, *DOES_NOT_EXIST will be set to 0 normally and set to 1
|
|
if the file does not exist. If the file does not exist and
|
|
DOES_NOT_EXIST is not NULL, the function will return -1 and will
|
|
not call ERROR_CALLBACK. On other errors, or if DOES_NOT_EXIST is
|
|
NULL, the function will call ERROR_CALLBACK before returning. */
|
|
extern int backtrace_open (const char *filename,
|
|
backtrace_error_callback error_callback,
|
|
void *data,
|
|
int *does_not_exist);
|
|
|
|
/* A view of the contents of a file. This supports mmap when
|
|
available. A view will remain in memory even after backtrace_close
|
|
is called on the file descriptor from which the view was
|
|
obtained. */
|
|
|
|
struct backtrace_view
|
|
{
|
|
/* The data that the caller requested. */
|
|
const void *data;
|
|
/* The base of the view. */
|
|
void *base;
|
|
/* The total length of the view. */
|
|
size_t len;
|
|
};
|
|
|
|
/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. Store the
|
|
result in *VIEW. Returns 1 on success, 0 on error. */
|
|
extern int backtrace_get_view (struct backtrace_state *state, int descriptor,
|
|
off_t offset, uint64_t size,
|
|
backtrace_error_callback error_callback,
|
|
void *data, struct backtrace_view *view);
|
|
|
|
/* Release a view created by backtrace_get_view. */
|
|
extern void backtrace_release_view (struct backtrace_state *state,
|
|
struct backtrace_view *view,
|
|
backtrace_error_callback error_callback,
|
|
void *data);
|
|
|
|
/* Close a file opened by backtrace_open. Returns 1 on success, 0 on
|
|
error. */
|
|
|
|
extern int backtrace_close (int descriptor,
|
|
backtrace_error_callback error_callback,
|
|
void *data);
|
|
|
|
/* Sort without using memory. */
|
|
|
|
extern void backtrace_qsort (void *base, size_t count, size_t size,
|
|
int (*compar) (const void *, const void *));
|
|
|
|
/* Allocate memory. This is like malloc. If ERROR_CALLBACK is NULL,
|
|
this does not report an error, it just returns NULL. */
|
|
|
|
extern void *backtrace_alloc (struct backtrace_state *state, size_t size,
|
|
backtrace_error_callback error_callback,
|
|
void *data) ATTRIBUTE_MALLOC;
|
|
|
|
/* Free memory allocated by backtrace_alloc. If ERROR_CALLBACK is
|
|
NULL, this does not report an error. */
|
|
|
|
extern void backtrace_free (struct backtrace_state *state, void *mem,
|
|
size_t size,
|
|
backtrace_error_callback error_callback,
|
|
void *data);
|
|
|
|
/* A growable vector of some struct. This is used for more efficient
|
|
allocation when we don't know the final size of some group of data
|
|
that we want to represent as an array. */
|
|
|
|
struct backtrace_vector
|
|
{
|
|
/* The base of the vector. */
|
|
void *base;
|
|
/* The number of bytes in the vector. */
|
|
size_t size;
|
|
/* The number of bytes available at the current allocation. */
|
|
size_t alc;
|
|
};
|
|
|
|
/* Grow VEC by SIZE bytes. Return a pointer to the newly allocated
|
|
bytes. Note that this may move the entire vector to a new memory
|
|
location. Returns NULL on failure. */
|
|
|
|
extern void *backtrace_vector_grow (struct backtrace_state *state, size_t size,
|
|
backtrace_error_callback error_callback,
|
|
void *data,
|
|
struct backtrace_vector *vec);
|
|
|
|
/* Finish the current allocation on VEC. Prepare to start a new
|
|
allocation. The finished allocation will never be freed. Returns
|
|
a pointer to the base of the finished entries, or NULL on
|
|
failure. */
|
|
|
|
extern void* backtrace_vector_finish (struct backtrace_state *state,
|
|
struct backtrace_vector *vec,
|
|
backtrace_error_callback error_callback,
|
|
void *data);
|
|
|
|
/* Release any extra space allocated for VEC. This may change
|
|
VEC->base. Returns 1 on success, 0 on failure. */
|
|
|
|
extern int backtrace_vector_release (struct backtrace_state *state,
|
|
struct backtrace_vector *vec,
|
|
backtrace_error_callback error_callback,
|
|
void *data);
|
|
|
|
/* Free the space managed by VEC. This will reset VEC. */
|
|
|
|
static inline void
|
|
backtrace_vector_free (struct backtrace_state *state,
|
|
struct backtrace_vector *vec,
|
|
backtrace_error_callback error_callback, void *data)
|
|
{
|
|
vec->alc += vec->size;
|
|
vec->size = 0;
|
|
backtrace_vector_release (state, vec, error_callback, data);
|
|
}
|
|
|
|
/* Read initial debug data from a descriptor, and set the
|
|
fileline_data, syminfo_fn, and syminfo_data fields of STATE.
|
|
Return the fileln_fn field in *FILELN_FN--this is done this way so
|
|
that the synchronization code is only implemented once. This is
|
|
called after the descriptor has first been opened. It will close
|
|
the descriptor if it is no longer needed. Returns 1 on success, 0
|
|
on error. There will be multiple implementations of this function,
|
|
for different file formats. Each system will compile the
|
|
appropriate one. */
|
|
|
|
extern int backtrace_initialize (struct backtrace_state *state,
|
|
const char *filename,
|
|
int descriptor,
|
|
backtrace_error_callback error_callback,
|
|
void *data,
|
|
fileline *fileline_fn);
|
|
|
|
/* An enum for the DWARF sections we care about. */
|
|
|
|
enum dwarf_section
|
|
{
|
|
DEBUG_INFO,
|
|
DEBUG_LINE,
|
|
DEBUG_ABBREV,
|
|
DEBUG_RANGES,
|
|
DEBUG_STR,
|
|
DEBUG_ADDR,
|
|
DEBUG_STR_OFFSETS,
|
|
DEBUG_LINE_STR,
|
|
DEBUG_RNGLISTS,
|
|
|
|
DEBUG_MAX
|
|
};
|
|
|
|
/* Data for the DWARF sections we care about. */
|
|
|
|
struct dwarf_sections
|
|
{
|
|
const unsigned char *data[DEBUG_MAX];
|
|
size_t size[DEBUG_MAX];
|
|
};
|
|
|
|
/* DWARF data read from a file, used for .gnu_debugaltlink. */
|
|
|
|
struct dwarf_data;
|
|
|
|
/* The load address mapping. */
|
|
|
|
#if defined(__FDPIC__) && defined(HAVE_DL_ITERATE_PHDR) && (defined(HAVE_LINK_H) || defined(HAVE_SYS_LINK_H))
|
|
|
|
#ifdef HAVE_LINK_H
|
|
#include <link.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_LINK_H
|
|
#include <sys/link.h>
|
|
#endif
|
|
|
|
#define libbacktrace_using_fdpic() (1)
|
|
|
|
struct libbacktrace_base_address
|
|
{
|
|
struct elf32_fdpic_loadaddr m;
|
|
};
|
|
|
|
#define libbacktrace_add_base(pc, base) \
|
|
((uintptr_t) (__RELOC_POINTER ((pc), (base).m)))
|
|
|
|
#else /* not _FDPIC__ */
|
|
|
|
#define libbacktrace_using_fdpic() (0)
|
|
|
|
struct libbacktrace_base_address
|
|
{
|
|
uintptr_t m;
|
|
};
|
|
|
|
#define libbacktrace_add_base(pc, base) ((pc) + (base).m)
|
|
|
|
#endif /* not _FDPIC__ */
|
|
|
|
/* Add file/line information for a DWARF module. */
|
|
|
|
extern int backtrace_dwarf_add (struct backtrace_state *state,
|
|
struct libbacktrace_base_address base_address,
|
|
const struct dwarf_sections *dwarf_sections,
|
|
int is_bigendian,
|
|
struct dwarf_data *fileline_altlink,
|
|
backtrace_error_callback error_callback,
|
|
void *data, fileline *fileline_fn,
|
|
struct dwarf_data **fileline_entry);
|
|
|
|
/* A data structure to pass to backtrace_syminfo_to_full. */
|
|
|
|
struct backtrace_call_full
|
|
{
|
|
backtrace_full_callback full_callback;
|
|
backtrace_error_callback full_error_callback;
|
|
void *full_data;
|
|
int ret;
|
|
};
|
|
|
|
/* A backtrace_syminfo_callback that can call into a
|
|
backtrace_full_callback, used when we have a symbol table but no
|
|
debug info. */
|
|
|
|
extern void backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
|
|
const char *symname,
|
|
uintptr_t symval,
|
|
uintptr_t symsize);
|
|
|
|
/* An error callback that corresponds to
|
|
backtrace_syminfo_to_full_callback. */
|
|
|
|
extern void backtrace_syminfo_to_full_error_callback (void *, const char *,
|
|
int);
|
|
|
|
/* A test-only hook for elf_uncompress_zdebug. */
|
|
|
|
extern int backtrace_uncompress_zdebug (struct backtrace_state *,
|
|
const unsigned char *compressed,
|
|
size_t compressed_size,
|
|
backtrace_error_callback, void *data,
|
|
unsigned char **uncompressed,
|
|
size_t *uncompressed_size);
|
|
|
|
/* A test-only hook for elf_zstd_decompress. */
|
|
|
|
extern int backtrace_uncompress_zstd (struct backtrace_state *,
|
|
const unsigned char *compressed,
|
|
size_t compressed_size,
|
|
backtrace_error_callback, void *data,
|
|
unsigned char *uncompressed,
|
|
size_t uncompressed_size);
|
|
|
|
/* A test-only hook for elf_uncompress_lzma. */
|
|
|
|
extern int backtrace_uncompress_lzma (struct backtrace_state *,
|
|
const unsigned char *compressed,
|
|
size_t compressed_size,
|
|
backtrace_error_callback, void *data,
|
|
unsigned char **uncompressed,
|
|
size_t *uncompressed_size);
|
|
|
|
}
|
|
|
|
#endif
|