123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- //===-- sanitizer_symbolizer.h ----------------------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // Symbolizer is used by sanitizers to map instruction address to a location in
- // source code at run-time. Symbolizer either uses __sanitizer_symbolize_*
- // defined in the program, or (if they are missing) tries to find and
- // launch "llvm-symbolizer" commandline tool in a separate process and
- // communicate with it.
- //
- // Generally we should try to avoid calling system library functions during
- // symbolization (and use their replacements from sanitizer_libc.h instead).
- //===----------------------------------------------------------------------===//
- #ifndef SANITIZER_SYMBOLIZER_H
- #define SANITIZER_SYMBOLIZER_H
- #include "sanitizer_common.h"
- #include "sanitizer_mutex.h"
- #include "sanitizer_vector.h"
- namespace __sanitizer {
- struct AddressInfo {
- // Owns all the string members. Storage for them is
- // (de)allocated using sanitizer internal allocator.
- uptr address;
- char *module;
- uptr module_offset;
- ModuleArch module_arch;
- u8 uuid[kModuleUUIDSize];
- uptr uuid_size;
- static const uptr kUnknown = ~(uptr)0;
- char *function;
- uptr function_offset;
- char *file;
- int line;
- int column;
- AddressInfo();
- // Deletes all strings and resets all fields.
- void Clear();
- void FillModuleInfo(const char *mod_name, uptr mod_offset, ModuleArch arch);
- void FillModuleInfo(const LoadedModule &mod);
- uptr module_base() const { return address - module_offset; }
- };
- // Linked list of symbolized frames (each frame is described by AddressInfo).
- struct SymbolizedStack {
- SymbolizedStack *next;
- AddressInfo info;
- static SymbolizedStack *New(uptr addr);
- // Deletes current, and all subsequent frames in the linked list.
- // The object cannot be accessed after the call to this function.
- void ClearAll();
- private:
- SymbolizedStack();
- };
- // For now, DataInfo is used to describe global variable.
- struct DataInfo {
- // Owns all the string members. Storage for them is
- // (de)allocated using sanitizer internal allocator.
- char *module;
- uptr module_offset;
- ModuleArch module_arch;
- char *file;
- uptr line;
- char *name;
- uptr start;
- uptr size;
- DataInfo();
- void Clear();
- };
- struct LocalInfo {
- char *function_name = nullptr;
- char *name = nullptr;
- char *decl_file = nullptr;
- unsigned decl_line = 0;
- bool has_frame_offset = false;
- bool has_size = false;
- bool has_tag_offset = false;
- sptr frame_offset;
- uptr size;
- uptr tag_offset;
- void Clear();
- };
- struct FrameInfo {
- char *module;
- uptr module_offset;
- ModuleArch module_arch;
- InternalMmapVector<LocalInfo> locals;
- void Clear();
- };
- class SymbolizerTool;
- class Symbolizer final {
- public:
- /// Initialize and return platform-specific implementation of symbolizer
- /// (if it wasn't already initialized).
- static Symbolizer *GetOrInit();
- static void LateInitialize();
- // Returns a list of symbolized frames for a given address (containing
- // all inlined functions, if necessary).
- SymbolizedStack *SymbolizePC(uptr address);
- bool SymbolizeData(uptr address, DataInfo *info);
- bool SymbolizeFrame(uptr address, FrameInfo *info);
- // The module names Symbolizer returns are stable and unique for every given
- // module. It is safe to store and compare them as pointers.
- bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
- uptr *module_address);
- const char *GetModuleNameForPc(uptr pc) {
- const char *module_name = nullptr;
- uptr unused;
- if (GetModuleNameAndOffsetForPC(pc, &module_name, &unused))
- return module_name;
- return nullptr;
- }
- // Release internal caches (if any).
- void Flush();
- // Attempts to demangle the provided C++ mangled name.
- const char *Demangle(const char *name);
- // Allow user to install hooks that would be called before/after Symbolizer
- // does the actual file/line info fetching. Specific sanitizers may need this
- // to distinguish system library calls made in user code from calls made
- // during in-process symbolization.
- typedef void (*StartSymbolizationHook)();
- typedef void (*EndSymbolizationHook)();
- // May be called at most once.
- void AddHooks(StartSymbolizationHook start_hook,
- EndSymbolizationHook end_hook);
- void RefreshModules();
- const LoadedModule *FindModuleForAddress(uptr address);
- void InvalidateModuleList();
- private:
- // GetModuleNameAndOffsetForPC has to return a string to the caller.
- // Since the corresponding module might get unloaded later, we should create
- // our owned copies of the strings that we can safely return.
- // ModuleNameOwner does not provide any synchronization, thus calls to
- // its method should be protected by |mu_|.
- class ModuleNameOwner {
- public:
- explicit ModuleNameOwner(Mutex *synchronized_by)
- : last_match_(nullptr), mu_(synchronized_by) {
- storage_.reserve(kInitialCapacity);
- }
- const char *GetOwnedCopy(const char *str);
- private:
- static const uptr kInitialCapacity = 1000;
- InternalMmapVector<const char*> storage_;
- const char *last_match_;
- Mutex *mu_;
- } module_names_;
- /// Platform-specific function for creating a Symbolizer object.
- static Symbolizer *PlatformInit();
- bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,
- uptr *module_offset,
- ModuleArch *module_arch);
- ListOfModules modules_;
- ListOfModules fallback_modules_;
- // If stale, need to reload the modules before looking up addresses.
- bool modules_fresh_;
- // Platform-specific default demangler, must not return nullptr.
- const char *PlatformDemangle(const char *name);
- static Symbolizer *symbolizer_;
- static StaticSpinMutex init_mu_;
- // Mutex locked from public methods of |Symbolizer|, so that the internals
- // (including individual symbolizer tools and platform-specific methods) are
- // always synchronized.
- Mutex mu_;
- IntrusiveList<SymbolizerTool> tools_;
- explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);
- static LowLevelAllocator symbolizer_allocator_;
- StartSymbolizationHook start_hook_;
- EndSymbolizationHook end_hook_;
- class SymbolizerScope {
- public:
- explicit SymbolizerScope(const Symbolizer *sym);
- ~SymbolizerScope();
- private:
- const Symbolizer *sym_;
- };
- };
- #ifdef SANITIZER_WINDOWS
- void InitializeDbgHelpIfNeeded();
- #endif
- } // namespace __sanitizer
- #endif // SANITIZER_SYMBOLIZER_H
|