// balst_stacktraceresolverimpl_elf.h -*-C++-*- // ---------------------------------------------------------------------------- // NOTICE // // This component is not up to date with current BDE coding standards, and // should not be used as an example for new development. // ---------------------------------------------------------------------------- #ifndef INCLUDED_BALST_STACKTRACERESOLVERIMPL_ELF #define INCLUDED_BALST_STACKTRACERESOLVERIMPL_ELF #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a utility to resolve ELF symbols in a stack trace. // //@CLASSES: // balst::StackTraceResolverImpl<Elf>: symbol resolution for ELF objects // //@SEE_ALSO: balst_stacktraceresolver_dwarfreader, // balst_stacktraceresolverimpl_windows, // balst_stacktraceresolverimpl_xcoff // //@DESCRIPTION: This component provides a class, // 'balst::StackTraceResolver<Elf>', that, given a vector of // 'balst::StackTraceFrame's that have only their 'address' fields set, // resolves all other fields in those frames. The Elf object file format is // used on Linux and Solaris platforms. The Elf format is described by // documents at: //: o 'http://en.wikipedia.org/wiki/Executable_and_Linkable_Format' //: o 'ftp://ftp.openwatcom.org/pub/devel/docs/elf-64-gen.pdf' //: o 'http://www.sco.com/developers/gabi/latest/contents.html' // ///Usage ///----- // This component is an implementation detail of 'balst' and is *not* intended // for direct client use. It is subject to change without notice. As such, a // usage example is not provided. #include <balscm_version.h> #include <balst_objectfileformat.h> #if defined(BALST_OBJECTFILEFORMAT_RESOLVER_ELF) #include <balst_stacktrace.h> #include <balst_stacktraceframe.h> #include <balst_stacktraceresolver_filehelper.h> #include <bdlma_heapbypassallocator.h> #include <bdls_filesystemutil.h> #include <bsls_types.h> #include <bsl_vector.h> namespace BloombergLP { namespace balst { template <class RESOLVER_POLICY> class StackTraceResolverImpl; // =================================================== // class StackTraceResolverImpl<ObjectFileFormat::Elf> // =================================================== template <> class StackTraceResolverImpl<ObjectFileFormat::Elf> { // This class provides a public static 'resolve' method that, given a // vector of 'StackTraceFrame's that have only their 'address' fields set, // resolves as many other fields in those frames as possible. The Elf // object file format is used on Linux and Solaris platforms. On Linux, // some Elf sections contain data in the DWARF format, which makes it // possible to resolve line numbers and file names. // TYPES typedef bsls::Types::UintPtr UintPtr; // 32 bit unsigned on 32 bit, 64 // bit unsigned on 64 bit. typedef bsls::Types::IntPtr IntPtr; // 32 bit signed on 32 bit, 64 // bit signed on 64 bit. typedef bdls::FilesystemUtil::Offset Offset; // Usually used for relative // offsets into a file. struct HiddenRec; // 'struct' defined locally in // in the imp file containing // additional information // DATA bdlma::HeapBypassAllocator d_hbpAlloc; // heap bypass allocator -- owned StackTrace *d_stackTrace_p; // pointer to stack trace object. // The frames contained in this // have their 'address' fields and // nothing else initialized upon // entry to 'resolve', which infers // as many other fields of them as // possible. char *d_scratchBufA_p; // scratch buffer A char *d_scratchBufB_p; // scratch buffer B char *d_scratchBufC_p; // scratch buffer C char *d_scratchBufD_p; // scratch buffer D HiddenRec& d_hidden; // reference to the 'HiddenRec'. bool d_demangle; // whether we demangle names private: // NOT IMPLEMENTED StackTraceResolverImpl(const StackTraceResolverImpl&); StackTraceResolverImpl& operator=(const StackTraceResolverImpl&); private: // PRIVATE CREATORS StackTraceResolverImpl(StackTrace *stackTrace, bool demanglingPreferredFlag); // Create an stack trace reolver that can populate other fields of the // specified '*stackTrace' object given previously populated 'address' // fields. Specify 'demangle', which indicates whether demangling of // symbols is to occur. // ~StackTraceResolverImpl() = default; // Destroy this object. // PRIVATE MANIPULATORS int loadSymbols(int matched); // Read the symbols from the symbol table of the current segment and // update the 'mangledSymbolName', 'symbolName', 'offsetFromSymbol', // and sometimes the 'SourceFileName' fields of stack frames constain // addresses within the code section of the current segment, where the // specified 'matched' is the number of addresses in the current // segment. Return 0 on success and a non-zero value otherwise. int resolveSegment(void *segmentBaseAddress, void *segmentPtr, UintPtr segmentSize, const char *libraryFileName); // Identify which stack trace frames in '*d_stackTrace_p' are in the // segment pointed at by the specified 'segmentPtr' of the specified // 'segmentSize', and initialize as many fields of those stack trace // frames as possible. The segment is defined in the executable file // or shared library 'libraryFileName'. Return 0 on success and a // non-zero value otherwise. // PRIVATE ACCESSORS void setFrameSymbolName(StackTraceFrame *frame, char *buffer, bsl::size_t bufferLen) const; // Set the 'symbolName' field of the specified 'frame', which must // already have the 'mangledSymbolName' field set, to the demangled // version of the 'mangledSymbolName' field. Use the specified // 'buffer' of specified length 'bufferLen' for temporary storage. If // 'd_demangle' is 'false' or we are otherwise unable to demangle, just // set it to the same as 'mangledSymbolName'. public: // CLASS METHOD static int resolve(StackTrace *stackTrace, bool demanglingPreferredFlag); // Populate information for the specified '*stackTrace', which contains // a sequence of randomly-accessible stack trace frames. Specify // 'demanglingPreferredFlag', to determine whether demangling is to // occur. The behavior is undefined unless all the 'address' field in // '*stackTrace' are valid and other fields are invalid. static int test(); // This function is just there to test how code deals with inline // functions in an include file. It does not provide any otherwise // useful functionality. Return a line number near the beginning of // the function in the low-order 14 bits of the result. Other bits of // the result are to be considered garbage. // MANIPULATOR int processLoadedImage(const char *fileName, const void *programHeaders, int numProgramHeaders, void *textSegPtr, void *baseAddress); // Process a loaded image found via the link map, either the main // program or some shared library. The specified 'fileName' is the // name of the file containing the image. If 'fileName == 0', the file // is the main program. The specified 'programHeaders' is a pointer to // an array of elf program headers and the specified // 'numProgramHeaders' is its length, it is a 'void *' because the type // 'ElfProgramHeader' is local to the implementation file. Specify one // of 'textSegPtr' and 'baseAddress', and the other as 0, this method // will infer the one specified as 0 from the other. Return 0 on // success and a non-zero value otherwise. Note that this method is // not to be called by external users of this component, it is only // public so a static routine in the implementation file can call it. // ACCESSOR int numUnmatchedFrames() const; // Return the number of frames in the stack trace that are still // unmatched. }; inline int StackTraceResolverImpl<ObjectFileFormat::Elf>::test() { StackTrace st; int ret = __LINE__; StackTraceResolverImpl<ObjectFileFormat::Elf> resolver(&st, true); return (resolver.numUnmatchedFrames() << 14) | ret; } } // close package namespace } // close enterprise namespace #endif #endif // ---------------------------------------------------------------------------- // Copyright 2015 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------