1 /*
2 * Copyright (c) 2019-2022 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file mos_util_debug_specific.cpp
24 //! \brief This module implments Linux MOS debug functionalities
25 //!
26
27 #include "mos_util_debug.h"
28 #include "mos_util_debug_specific.h"
29 #include "mos_oca_rtlog_mgr_defs.h"
30 #include "mos_interface.h"
31 #include <stdlib.h>
32
33 #if MOS_MESSAGES_ENABLED
34
35 #include "mos_utilities_specific.h"
36 #include "media_user_setting.h"
37 #include "string.h"
38 #include <time.h> //get_clocktime
39 #include <unistd.h> //read, lseek
40 #include <fcntl.h> //open
41
42 #ifdef ANDROID
43 #include <android/log.h>
44 #else
45 #include <signal.h>
46 #endif // ANDROID
47
48 #define MOS_ULT_LOG_PATH_PREFIX "./"
49
50 //!
51 //! \brief HLT log file prefix
52 //!
53 #define MOS_LOG_PATH_PREFIX "/etc/log"
54
55 #define HLT_COPY_BUFFER_LENGTH 200
56
MosHltpCopyFile(PFILE pFile,const PCCHAR szFileName)57 MOS_STATUS MosUtilDebug::MosHltpCopyFile(PFILE pFile, const PCCHAR szFileName)
58 {
59 PFILE pFileSrc;
60 char szBuffer[HLT_COPY_BUFFER_LENGTH];
61 int32_t nRead;
62
63 nRead = 0;
64 if( (pFileSrc = fopen(szFileName , "r" )) == nullptr)
65 {
66 printf("open file %s failed", szFileName);
67 return MOS_STATUS_FILE_OPEN_FAILED;
68 }
69 do
70 {
71 nRead = fread(szBuffer, 1, HLT_COPY_BUFFER_LENGTH, pFileSrc);
72 if( ( nRead > 0 ) && (nRead <= HLT_COPY_BUFFER_LENGTH) )
73 {
74 fwrite(szBuffer, 1, nRead, pFile);
75 }
76 } while( nRead > 0 );
77
78 fclose(pFileSrc);
79
80 return MOS_STATUS_SUCCESS;
81 }
82
MosHltpPreface(PFILE pFile)83 void MosUtilDebug::MosHltpPreface(PFILE pFile)
84 {
85 time_t rawtime;
86 struct tm* timeinfo;
87
88 time(&rawtime);
89 timeinfo = localtime(&rawtime);
90 if (timeinfo == nullptr)
91 {
92 printf("fail to call localtime in MosHltpPreface\n");
93 return;
94 }
95
96 fprintf(pFile, "//\n"
97 "// HLT log file: version1.0\n"
98 "// Logtime %d-%d-%d %d:%d:%d; Machine=",
99 timeinfo->tm_year,timeinfo->tm_mon, timeinfo->tm_yday,
100 timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);
101
102 fwrite("\n", 1, 1, pFile);
103 MosHltpCopyFile(pFile, "/etc/hosts");
104
105 // This section has been temporarily commented out because it's printing a non standard character to the logfile and corrupting it.
106 /*
107 fprintf(pFile, "\n"
108 "// PID=%d; Process name=",
109 getpid());
110
111 MosHltpCopyFile(pFile, "/proc/self/cmdline");
112 */
113
114 fwrite("\n", 1, 1, pFile);
115
116 MosHltpCopyFile(pFile, "/proc/version");
117 // Linux version 2.6.35-22-generic (buildd@rothera) (gcc version 4.4.5 (Ubuntu/Linaro // 4.4.4-14ubuntu4) ) #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010
118
119 if (m_mosMsgParams.bEnableMaps)
120 {
121 fwrite("\n// Loaded modules:\n", 20, 1, pFile);
122
123 MosHltpCopyFile(pFile, "/proc/self/maps");
124 fwrite("\n", 1, 1, pFile);
125 }
126
127 fflush(pFile);
128 }
129
MosLogFileNamePrefix(char * fileNamePrefix,MediaUserSettingSharedPtr userSettingPtr)130 MOS_STATUS MosUtilDebug::MosLogFileNamePrefix(char *fileNamePrefix, MediaUserSettingSharedPtr userSettingPtr)
131 {
132 int32_t iRet = 0;
133 MOS_STATUS eStatus = MOS_STATUS_UNKNOWN;
134 MediaUserSetting::Value outValue;
135
136 if (MosUtilities::m_mosUltFlag && (*MosUtilities::m_mosUltFlag))
137 {
138 iRet = MosUtilities::MosSecureStringPrint(
139 fileNamePrefix,
140 MOS_MAX_HLT_FILENAME_LEN,
141 MOS_MAX_HLT_FILENAME_LEN,
142 MOS_ULT_LOG_PATH_PREFIX);
143
144 if (iRet > 0)
145 {
146 eStatus = MOS_STATUS_SUCCESS;
147 }
148
149 return eStatus;
150 }
151
152 eStatus = ReadUserSetting(
153 userSettingPtr,
154 outValue,
155 __MOS_USER_FEATURE_KEY_MESSAGE_HLT_OUTPUT_DIRECTORY,
156 MediaUserSetting::Group::Device);
157
158 if(outValue.ConstString().size() > 0 && outValue.ConstString().size() < MOS_MAX_HLT_FILENAME_LEN)
159 {
160 MosUtilities::MosSecureStrcpy(fileNamePrefix, MOS_MAX_HLT_FILENAME_LEN, outValue.ConstString().c_str());
161 }
162 else // If the user feature key was not found or not valid, create it with the default value.
163 {
164 MOS_OS_NORMALMESSAGE("eStatus = %x, outValue.size = %x", eStatus, outValue.ConstString().size());
165
166 iRet = MosUtilities::MosSecureStringPrint(
167 fileNamePrefix,
168 MOS_MAX_HLT_FILENAME_LEN,
169 MOS_MAX_HLT_FILENAME_LEN,
170 MOS_LOG_PATH_PREFIX);
171
172 if (iRet > 0)
173 {
174 eStatus = ReportUserSetting(
175 userSettingPtr,
176 __MOS_USER_FEATURE_KEY_MESSAGE_HLT_OUTPUT_DIRECTORY,
177 fileNamePrefix,
178 MediaUserSetting::Group::Device);
179 }
180 else
181 {
182 return MOS_STATUS_UNKNOWN;
183 }
184 }
185
186 return eStatus;
187 }
188
MosMessageInternal(MOS_MESSAGE_LEVEL level,MOS_COMPONENT_ID compID,uint8_t subCompID,const PCCHAR functionName,int32_t lineNum,const PCCHAR message,va_list var_args)189 void MosUtilDebug::MosMessageInternal(
190 MOS_MESSAGE_LEVEL level,
191 MOS_COMPONENT_ID compID,
192 uint8_t subCompID,
193 const PCCHAR functionName,
194 int32_t lineNum,
195 const PCCHAR message,
196 va_list var_args)
197 {
198 uint32_t nLen = 0;
199 PCCHAR func = functionName;
200 static MOS_MUTEX mosMsgMutex = PTHREAD_MUTEX_INITIALIZER;
201
202 if (MosShouldPrintMessage(level, compID, subCompID, message) == false)
203 {
204 return;
205 }
206 if (level == MOS_MESSAGE_LVL_CRITICAL)
207 {
208 OcaOnMosCriticalMessage(functionName, lineNum);
209 }
210
211 MosUtilities::MosLockMutex(&mosMsgMutex);
212 // Proceed to print the message
213 if (functionName == nullptr)
214 {
215 MosUtilities::MosSecureStringPrint(m_mosMsgParams.g_MosMsgBuffer,
216 MOS_MAX_MSG_BUF_SIZE,
217 (MOS_MAX_MSG_BUF_SIZE-1),
218 "%s%s - ",
219 m_mosComponentName[compID],
220 m_mosLogLevelName[level]);
221 nLen = strlen(m_mosMsgParams.g_MosMsgBuffer);
222 }
223 else
224 {
225 #if USE_PRETTY_FUNCTION
226 // call MosGetClassMethod to convert pretty function to class::function
227 // return string locate in static memory, mutex should be hold.
228 func = MosGetClassMethod(functionName);
229 #endif //USE_PRETTY_FUNCTION
230 if (lineNum < 0)
231 {
232 // no line number output
233 MosUtilities::MosSecureStringPrint(m_mosMsgParams.g_MosMsgBuffer,
234 MOS_MAX_MSG_BUF_SIZE,
235 (MOS_MAX_MSG_BUF_SIZE-1),
236 "%s%s - %s",
237 m_mosComponentName[compID],
238 m_mosLogLevelName[level],
239 func);
240 nLen = strlen(m_mosMsgParams.g_MosMsgBuffer);
241 }
242 else
243 {
244 MosUtilities::MosSecureStringPrint(m_mosMsgParams.g_MosMsgBuffer,
245 MOS_MAX_MSG_BUF_SIZE,
246 (MOS_MAX_MSG_BUF_SIZE-1),
247 "%s%s - %s:%d: ",
248 m_mosComponentName[compID],
249 m_mosLogLevelName[level],
250 func,
251 lineNum);
252 nLen = strlen(m_mosMsgParams.g_MosMsgBuffer);
253 }
254 }
255 MosUtilities::MosSecureVStringPrint(m_mosMsgParams.g_MosMsgBuffer + nLen,
256 MOS_MAX_MSG_BUF_SIZE - nLen,
257 (MOS_MAX_MSG_BUF_SIZE - 1 - nLen),
258 message,
259 var_args);
260
261 // Dump message to debugger if print to output window enabled
262 if (m_mosMsgParams.bUseOutputDebugString)
263 {
264 printf("%s\n", m_mosMsgParams.g_MosMsgBuffer);
265 }
266
267 // Write to log file if HLT enabled. File already open to add preface information
268 if (m_mosMsgParams.bUseHybridLogTrace)
269 {
270 if (m_mosMsgParams.pLogFile != nullptr)
271 {
272 nLen = strlen(m_mosMsgParams.g_MosMsgBuffer);
273 fwrite(m_mosMsgParams.g_MosMsgBuffer, nLen, 1, m_mosMsgParams.pLogFile);
274 fprintf(m_mosMsgParams.pLogFile, "\n");
275 }
276 else
277 {
278 printf("ERROR: m_mosMsgParams.pLogFile is NULL!\n");
279 }
280 }
281 MosUtilities::MosUnlockMutex(&mosMsgMutex);
282
283 return;
284 }
285
286 //!
287 //! When printing from a C++ class, we'd like the class and function to be printed.
288 //! With our current Linux compiler, __FUNCTION__ does not include the class name.
289 //! So we use __PRETTY_FUNCTION__ and call MosGetClassMethod(__PRETTY_FUNCTION__) to remove extra data.
290 //! This is not needed for prints from C files so they will usually use __FUNCTION__.
291 //!
292 #if USE_PRETTY_FUNCTION
293
294 //!
295 //! functionName is used to temporarily store the concatinated __PRETTY_FUNCTION__,
296 //! when calling MosGetClassMethod().
297 //!
298
MosGetClassMethod(PCCHAR pcPrettyFunction)299 PCCHAR MosUtilDebug::MosGetClassMethod(PCCHAR pcPrettyFunction)
300 {
301 PCCHAR end = nullptr;
302 uint32_t len = 0;
303 static char functionName[256] = {}; // 256 is an arbitrary long enough size.
304
305 memset(functionName, '\0', sizeof(functionName));
306
307 // Find the first '(', if it exists.
308 end = strchr(pcPrettyFunction, '(');
309
310 // We want to copy pcPrettyFunction into gFunction, only up to the first '('.
311 len = end ? (uint32_t)(end - pcPrettyFunction) : strlen(pcPrettyFunction);
312
313 MosUtilities::MosSecureMemcpy(functionName, sizeof(functionName), pcPrettyFunction, len);
314
315 // dismiss anything before the last ' '.
316 return strrchr(functionName, ' ') ? strrchr(functionName, ' ') + 1 : functionName;
317 }
318
319 #endif // USE_PRETTY_FUNCTION
320
321 #if MOS_ASSERT_ENABLED
322
MosAssert(MOS_COMPONENT_ID compID,uint8_t subCompID)323 void MosUtilDebug::MosAssert(MOS_COMPONENT_ID compID, uint8_t subCompID)
324 {
325 if (MosShouldAssert(compID, subCompID) == false)
326 {
327 return;
328 }
329
330 //! NOTE:
331 //! If you hit asserts here and do not want to, you can cancel them by updating user feature keys under __MEDIA_USER_FEATURE_SUBKEY_INTERNAL.
332 //! These keys can be found in USER_FEATURE_FILE (currently "/etc/igfx_user_feature.txt").
333 //! First figure out what component is asserting (check element number compID in MOS_COMPONENT_ID).
334 //! Then in the user feature key "<component> Message Tags", set the forth bit to zero.
335 raise(SIGTRAP);
336 }
337
338 #endif // MOS_ASSERT_ENABLED
339
340 #endif // MOS_MESSAGES_ENABLED
341