|  | /* internal.h -- Internal header file for stack backtrace library. | 
|  | Copyright (C) 2012-2024 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) */ | 
|  |  | 
|  | /* 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); | 
|  |  | 
|  | /* 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; | 
|  | }; | 
|  |  | 
|  | /* 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; | 
|  |  | 
|  | /* Add file/line information for a DWARF module.  */ | 
|  |  | 
|  | extern int backtrace_dwarf_add (struct backtrace_state *state, | 
|  | uintptr_t 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 |