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