1 /*
2  * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 
26 #ifndef SHARE_VM_UTILITIES_DECODER_HPP
27 #define SHARE_VM_UTILITIES_DECODER_HPP
28 
29 #include "memory/allocation.hpp"
30 #include "runtime/mutex.hpp"
31 #include "runtime/mutexLocker.hpp"
32 #include "utilities/ostream.hpp"
33 
34 class AbstractDecoder : public CHeapObj<mtInternal> {
35 public:
36   // status code for decoding native C frame
37   enum decoder_status {
38          not_available = -10,  // real decoder is not available
39          no_error = 0,         // no error encountered
40          out_of_memory,        // out of memory
41          file_invalid,         // invalid elf file
42          file_not_found,       // could not found symbol file (on windows), such as jvm.pdb or jvm.map
43          helper_func_error,    // decoding functions not found (Windows only)
44          helper_init_error     // SymInitialize failed (Windows only)
45   };
46 
47 protected:
48   decoder_status  _decoder_status;
49 
50 public:
~AbstractDecoder()51   virtual ~AbstractDecoder() {}
52 
53   // decode an pc address to corresponding function name and an offset from the beginning of
54   // the function
55   //
56   // Note: the 'base' variant does not demangle names. The
57   // demangling that was done systematically in the 'modulepath' variant
58   // is now optional.
59   virtual bool decode(address pc, char* buf, int buflen, int* offset,
60                       const char* modulepath = NULL, bool demangle = true) = 0;
61   virtual bool decode(address pc, char* buf, int buflen, int* offset, const void* base) = 0;
62 
63   // demangle a C++ symbol
64   virtual bool demangle(const char* symbol, char* buf, int buflen) = 0;
65 
status() const66   virtual decoder_status status() const {
67     return _decoder_status;
68   }
69 
has_error() const70   virtual bool has_error() const {
71     return is_error(_decoder_status);
72   }
73 
is_error(decoder_status status)74   static bool is_error(decoder_status status) {
75     return (status > no_error);
76   }
77 };
78 
79 // Do nothing decoder
80 class NullDecoder : public AbstractDecoder {
81 public:
NullDecoder()82   NullDecoder() {
83     _decoder_status = not_available;
84   }
85 
~NullDecoder()86   virtual ~NullDecoder() {};
87 
decode(address pc,char * buf,int buflen,int * offset,const char * modulepath,bool demangle)88   virtual bool decode(address pc, char* buf, int buflen, int* offset,
89                       const char* modulepath, bool demangle) {
90     return false;
91   }
92 
decode(address pc,char * buf,int buflen,int * offset,const void * base)93   virtual bool decode(address pc, char* buf, int buflen, int* offset, const void* base) {
94     return false;
95   }
96 
demangle(const char * symbol,char * buf,int buflen)97   virtual bool demangle(const char* symbol, char* buf, int buflen) {
98     return false;
99   }
100 };
101 
102 class Decoder : AllStatic {
103 public:
104   static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL, bool demangle = true);
decode(address pc,char * buf,int buflen,int * offset,bool demangle)105   static bool decode(address pc, char* buf, int buflen, int* offset, bool demangle) {
106     return decode(pc, buf, buflen, offset, (const char*) NULL, demangle);
107   }
108   static bool decode(address pc, char* buf, int buflen, int* offset, const void* base);
109   static bool demangle(const char* symbol, char* buf, int buflen);
110 
111   // Attempts to retrieve source file name and line number associated with a pc.
112   // If buf != NULL, points to a buffer of size buflen which will receive the
113   // file name. File name will be silently truncated if output buffer is too small.
114   static bool get_source_info(address pc, char* buf, size_t buflen, int* line);
115 
116   static void print_state_on(outputStream* st);
117 
118 protected:
119   // shared decoder instance, _shared_instance_lock is needed
120   static AbstractDecoder* get_shared_instance();
121   // a private instance for error handler. Error handler can be
122   // triggered almost everywhere, including signal handler, where
123   // no lock can be taken. So the shared decoder can not be used
124   // in this scenario.
125   static AbstractDecoder* get_error_handler_instance();
126 
127   static AbstractDecoder* create_decoder();
128 private:
129   static AbstractDecoder*     _shared_decoder;
130   static AbstractDecoder*     _error_handler_decoder;
131   static NullDecoder          _do_nothing_decoder;
132 
133 protected:
134   static Mutex* shared_decoder_lock();
135 
136   friend class DecoderLocker;
137 };
138 
139 class DecoderLocker : public MutexLockerEx {
140   AbstractDecoder* _decoder;
141   inline bool is_first_error_thread();
142 public:
143   DecoderLocker();
decoder()144   AbstractDecoder* decoder() {
145     return _decoder;
146   }
147 };
148 
149 #endif // SHARE_VM_UTILITIES_DECODER_HPP
150