7117774fa147c61248846121599e1d8c788a2970
[platform/core/uifw/dali-core.git] / dali / public-api / common / dali-common.cpp
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/public-api/common/dali-common.h>
20
21 // EXTERNAL INCLUDES
22 #include <stdlib.h>
23 #include <string>
24 #include <cstdio>
25
26 #include <execinfo.h>
27 #include <cxxabi.h>
28
29 #include <cstring>
30
31 // INTERNAL INCLUDES
32 #include <dali/integration-api/debug.h>
33
34 namespace Dali
35 {
36
37 #if defined(BACKTRACE_ENABLED)
38
39 namespace
40 {
41 const int MAX_NUM_STACK_FRAMES = 25;
42 }
43
44 std::string Demangle(const char* symbol)
45 {
46   std::string result;
47
48   // backtrace ::=  <filename>'('['_'<mangled-symbol>'_']['+'<offset>]')'
49   // Only want <mangled-symbol>:
50   const char* openParen = strchr(symbol, '(');
51   if(openParen != NULL)
52   {
53     const char* startOfToken = openParen + 1;
54     const char* plus = strchr(startOfToken, '+');
55     const char* closeParen = strchr(startOfToken, ')');
56     const char* endOfToken = NULL;
57     if(plus != NULL)
58     {
59       endOfToken = plus;
60     }
61     else if(closeParen != NULL)
62     {
63       endOfToken = closeParen;
64     }
65     if(endOfToken != NULL)
66     {
67       size_t tokenLength = endOfToken - startOfToken;
68
69       // Allocate space for symbol
70       char *mangledSymbol = reinterpret_cast< char* >( malloc( tokenLength + 1u ) );
71       if(mangledSymbol != NULL)
72       {
73         strncpy(mangledSymbol, startOfToken, tokenLength);
74         mangledSymbol[tokenLength] = '\0';
75
76         size_t size;
77         int    status;
78         char*  demangled=NULL;
79         demangled = abi::__cxa_demangle( mangledSymbol, NULL, &size, &status );
80         if( demangled != NULL )
81         {
82           result = demangled;
83           free(demangled); // demangle() allocates returned string, so free it
84         }
85         else
86         {
87           result = symbol;
88         }
89         free(mangledSymbol);
90       }
91     }
92   }
93
94   return result;
95 }
96
97 DALI_CORE_API DaliException::DaliException( const char* location, const char* condition )
98 : location( location ), condition( condition )
99 {
100   // Note, if a memory error has occured, then the backtrace won't work - backtrace_symbols relies on
101   // allocating memory.
102
103   // Initial dlog error message is output in DALI_ASSERT_ALWAYS macro
104   // Also output on stderr
105 #if defined(DEBUG_ENABLED)
106   fprintf(stderr, "Exception: \n%s\n thrown at %s\nSee dlog for backtrace\n", condition, location);
107 #else
108   fprintf(stderr, "Exception: \n%s\n thrown\nSee dlog for backtrace\n", condition );
109 #endif
110
111   DALI_LOG_ERROR_NOFN("Backtrace:\n");
112
113   std::string tmpString("\n=== DALi Native Excetion Info ===");
114   //appending condition
115   tmpString.append("\nCONDITION: ");
116   tmpString.append(condition);
117   //appending back-trace
118   tmpString.append("\nBACKTRACE: \n");
119
120   void* frameArray[MAX_NUM_STACK_FRAMES];
121   int nSize = backtrace(frameArray, MAX_NUM_STACK_FRAMES);
122   char** symbols = backtrace_symbols(frameArray, nSize);
123   for(int i=1; i< nSize; i++)
124   {
125     std::string demangled_symbol = Demangle(symbols[i]);
126     DALI_LOG_ERROR_NOFN("[%02d]   %s\n", i, demangled_symbol.c_str() );
127
128     tmpString.append("[");
129     tmpString.append(std::to_string(i));
130     tmpString.append("]  ");
131     tmpString.append(demangled_symbol);
132     tmpString.append("\n");
133   }
134   free(symbols);
135
136   tmpString.append("=================================\n\0");
137
138   info = static_cast<char*>(malloc( tmpString.size() * sizeof(char)) );
139   strncpy(info, tmpString.c_str(), tmpString.size());
140 }
141
142 #else // BACKTRACE_ENABLED
143
144 DALI_CORE_API DaliException::DaliException( const char* location, const char* condition )
145 : location( location ), condition( condition )
146 {
147 #if defined(DEBUG_ENABLED)
148   printf("Exception: \n%s\n thrown at %s\n", condition, location );
149 #else
150   printf("Exception: \n%s\n thrown\n", condition );
151 #endif
152 }
153
154
155 #endif // BACKTRACE_ENABLED
156
157 DALI_CORE_API void DaliAssertMessage( const char* location, const char* condition )
158 {
159 #if defined(DEBUG_ENABLED)
160   DALI_LOG_ERROR_NOFN( "Assert (%s) failed in: %s\n", condition, location );
161 #else
162   DALI_LOG_ERROR_NOFN( "Assert (%s) failed\n", condition );
163 #endif
164 }
165
166 } // Dali