| /* 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 |