• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
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 #include "chre/util/system/debug_dump.h"
18 
19 #include <cinttypes>
20 #include <cstdio>
21 
22 #include "chre/platform/log.h"
23 
24 namespace chre {
25 
print(const char * formatStr,...)26 void DebugDumpWrapper::print(const char *formatStr, ...) {
27   va_list argList;
28   va_start(argList, formatStr);
29   printVaList(formatStr, argList);
30   va_end(argList);
31 }
32 
printVaList(const char * formatStr,va_list argList)33 void DebugDumpWrapper::printVaList(const char *formatStr, va_list argList) {
34   va_list argListCopy;
35   va_copy(argListCopy, argList);
36 
37   if (mCurrBuff != nullptr || allocNewBuffer()) {
38     bool sizeValid;
39     size_t sizeOfStr;
40     if (!insertString(formatStr, argList, &sizeValid, &sizeOfStr)) {
41       if (!sizeValid) {
42         LOGE("Error inserting string into buffer in debug dump");
43       } else if (sizeOfStr >= kBuffSize) {
44         LOGE(
45             "String was too large to fit in a single buffer for debug dump "
46             "print");
47       } else if (allocNewBuffer()) {
48         // Insufficient space left in buffer, allocate a new one and it's
49         // guaranteed to succeed.
50         bool success =
51             insertString(formatStr, argListCopy, &sizeValid, &sizeOfStr);
52         CHRE_ASSERT(success);
53       }
54     }
55   }
56   va_end(argListCopy);
57 }
58 
allocNewBuffer()59 bool DebugDumpWrapper::allocNewBuffer() {
60   mCurrBuff = static_cast<char *>(memoryAlloc(kBuffSize));
61   if (mCurrBuff == nullptr) {
62     LOG_OOM();
63   } else {
64     mBuffers.emplace_back(mCurrBuff);
65     mBuffPos = 0;
66     mCurrBuff[0] = '\0';
67   }
68   return mCurrBuff != nullptr;
69 }
70 
insertString(const char * formatStr,va_list argList,bool * sizeValid,size_t * sizeOfStr)71 bool DebugDumpWrapper::insertString(const char *formatStr, va_list argList,
72                                     bool *sizeValid, size_t *sizeOfStr) {
73   CHRE_ASSERT(mCurrBuff != nullptr);
74   CHRE_ASSERT(mBuffPos <= kBuffSize);
75 
76   // Buffer space left
77   size_t spaceLeft = kBuffSize - mBuffPos;
78 
79   // Note strLen doesn't count the terminating null character.
80   int strLen = vsnprintf(&mCurrBuff[mBuffPos], spaceLeft, formatStr, argList);
81   size_t strSize = static_cast<size_t>(strLen);
82 
83   bool success = false;
84   *sizeValid = false;
85   if (strLen >= 0) {
86     *sizeValid = true;
87 
88     if (strSize >= spaceLeft) {
89       // Chop off the incomplete string.
90       mCurrBuff[mBuffPos] = '\0';
91     } else {
92       success = true;
93       mBuffPos += strSize;
94     }
95   }
96 
97   *sizeOfStr = strSize;
98   return success;
99 }
100 
logErrorHistogram(const uint32_t * histogram,uint8_t histogramLength)101 void DebugDumpWrapper::logErrorHistogram(const uint32_t *histogram,
102                                          uint8_t histogramLength) {
103   print("     [");
104   for (int i = 0; i < histogramLength; i++) {
105     print("%" PRIu32, histogram[i]);
106     if (i < histogramLength - 1) {
107       print(",");
108     }
109   }
110   print("]\n");
111 }
112 
113 }  // namespace chre
114