blob: 4464032c8e5b0253dda67a13405f99a00ec7d588 [file] [log] [blame]
Mathias Agopian4ea13dc2013-05-06 20:20:50 -07001/*
2 * Copyright (C) 2005 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
Martijn Coenen4080edc2016-05-04 14:17:02 +020017#include <hwbinder/Debug.h>
Colin Crossdd6dafb2017-06-22 12:29:13 -070018#include <hwbinder/ProcessState.h>
Mathias Agopian4ea13dc2013-05-06 20:20:50 -070019
20#include <utils/misc.h>
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <ctype.h>
25
26namespace android {
Martijn Coenenf75a23d2016-08-01 11:55:17 +020027namespace hardware {
Mathias Agopian4ea13dc2013-05-06 20:20:50 -070028
29// ---------------------------------------------------------------------
30
31static const char indentStr[] =
32" "
33" ";
34
35const char* stringForIndent(int32_t indentLevel)
36{
37 ssize_t off = sizeof(indentStr)-1-(indentLevel*2);
38 return indentStr + (off < 0 ? 0 : off);
39}
40
41// ---------------------------------------------------------------------
42
Colin Crossf0487982014-02-05 17:42:44 -080043static void defaultPrintFunc(void* /*cookie*/, const char* txt)
Mathias Agopian4ea13dc2013-05-06 20:20:50 -070044{
45 printf("%s", txt);
46}
47
48// ---------------------------------------------------------------------
49
50static inline int isident(int c)
51{
52 return isalnum(c) || c == '_';
53}
54
55static inline bool isasciitype(char c)
56{
57 if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true;
58 return false;
59}
60
61static inline char makehexdigit(uint32_t val)
62{
63 return "0123456789abcdef"[val&0xF];
64}
65
66static char* appendhexnum(uint32_t val, char* out)
67{
68 for( int32_t i=28; i>=0; i-=4 ) {
69 *out++ = makehexdigit( val>>i );
70 }
71 *out = 0;
72 return out;
73}
74
75static char* appendcharornum(char c, char* out, bool skipzero = true)
76{
77 if (skipzero && c == 0) return out;
78
79 if (isasciitype(c)) {
80 *out++ = c;
81 return out;
82 }
83
84 *out++ = '\\';
85 *out++ = 'x';
86 *out++ = makehexdigit(c>>4);
87 *out++ = makehexdigit(c);
88 return out;
89}
90
91static char* typetostring(uint32_t type, char* out,
92 bool fullContext = true,
93 bool strict = false)
94{
95 char* pos = out;
96 char c[4];
97 c[0] = (char)((type>>24)&0xFF);
98 c[1] = (char)((type>>16)&0xFF);
99 c[2] = (char)((type>>8)&0xFF);
100 c[3] = (char)(type&0xFF);
101 bool valid;
102 if( !strict ) {
103 // now even less strict!
104 // valid = isasciitype(c[3]);
105 valid = true;
106 int32_t i = 0;
107 bool zero = true;
108 while (valid && i<3) {
109 if (c[i] == 0) {
110 if (!zero) valid = false;
111 } else {
112 zero = false;
113 //if (!isasciitype(c[i])) valid = false;
114 }
115 i++;
116 }
117 // if all zeros, not a valid type code.
118 if (zero) valid = false;
119 } else {
120 valid = isident(c[3]) ? true : false;
121 int32_t i = 0;
122 bool zero = true;
123 while (valid && i<3) {
124 if (c[i] == 0) {
125 if (!zero) valid = false;
126 } else {
127 zero = false;
128 if (!isident(c[i])) valid = false;
129 }
130 i++;
131 }
132 }
133 if( valid && (!fullContext || c[0] != '0' || c[1] != 'x') ) {
134 if( fullContext ) *pos++ = '\'';
135 pos = appendcharornum(c[0], pos);
136 pos = appendcharornum(c[1], pos);
137 pos = appendcharornum(c[2], pos);
138 pos = appendcharornum(c[3], pos);
139 if( fullContext ) *pos++ = '\'';
140 *pos = 0;
141 return pos;
142 }
Dan Austinf4865ca2015-10-21 11:28:59 -0700143
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700144 if( fullContext ) {
145 *pos++ = '0';
146 *pos++ = 'x';
147 }
148 return appendhexnum(type, pos);
149}
150
151void printTypeCode(uint32_t typeCode, debugPrintFunc func, void* cookie)
152{
153 char buffer[32];
154 char* end = typetostring(typeCode, buffer);
155 *end = 0;
156 func ? (*func)(cookie, buffer) : defaultPrintFunc(cookie, buffer);
157}
158
159void printHexData(int32_t indent, const void *buf, size_t length,
160 size_t bytesPerLine, int32_t singleLineBytesCutoff,
161 size_t alignment, bool cStyle,
162 debugPrintFunc func, void* cookie)
163{
164 if (alignment == 0) {
165 if (bytesPerLine >= 16) alignment = 4;
166 else if (bytesPerLine >= 8) alignment = 2;
167 else alignment = 1;
168 }
Yi Kong55d41072018-07-23 14:55:39 -0700169 if (func == nullptr) func = defaultPrintFunc;
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700170
171 size_t offset;
Dan Austinf4865ca2015-10-21 11:28:59 -0700172
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700173 unsigned char *pos = (unsigned char *)buf;
Dan Austinf4865ca2015-10-21 11:28:59 -0700174
Yi Kong55d41072018-07-23 14:55:39 -0700175 if (pos == nullptr) {
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700176 if (singleLineBytesCutoff < 0) func(cookie, "\n");
177 func(cookie, "(NULL)");
178 return;
179 }
Dan Austinf4865ca2015-10-21 11:28:59 -0700180
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700181 if (length == 0) {
182 if (singleLineBytesCutoff < 0) func(cookie, "\n");
183 func(cookie, "(empty)");
184 return;
185 }
Dan Austinf4865ca2015-10-21 11:28:59 -0700186
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700187 if ((int32_t)length < 0) {
188 if (singleLineBytesCutoff < 0) func(cookie, "\n");
189 char buf[64];
190 sprintf(buf, "(bad length: %zu)", length);
191 func(cookie, buf);
192 return;
193 }
Dan Austinf4865ca2015-10-21 11:28:59 -0700194
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700195 char buffer[256];
196 static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1);
Dan Austinf4865ca2015-10-21 11:28:59 -0700197
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700198 if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine;
Dan Austinf4865ca2015-10-21 11:28:59 -0700199
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700200 const bool oneLine = (int32_t)length <= singleLineBytesCutoff;
201 bool newLine = false;
202 if (cStyle) {
203 indent++;
204 func(cookie, "{\n");
205 newLine = true;
206 } else if (!oneLine) {
207 func(cookie, "\n");
208 newLine = true;
209 }
Dan Austinf4865ca2015-10-21 11:28:59 -0700210
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700211 for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
212 long remain = length;
213
214 char* c = buffer;
215 if (!oneLine && !cStyle) {
216 sprintf(c, "0x%08x: ", (int)offset);
217 c += 12;
218 }
219
220 size_t index;
221 size_t word;
Dan Austinf4865ca2015-10-21 11:28:59 -0700222
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700223 for (word = 0; word < bytesPerLine; ) {
224
Martijn Coenen0d9dda22017-05-08 09:24:15 -0700225 size_t align_offset = alignment-(alignment?1:0);
226 if (remain > 0 && (size_t)remain <= align_offset) {
227 align_offset = remain - 1;
228 }
229 const size_t startIndex = word+align_offset;
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700230
231 for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
Dan Austinf4865ca2015-10-21 11:28:59 -0700232
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700233 if (!cStyle) {
234 if (index == 0 && word > 0 && alignment > 0) {
235 *c++ = ' ';
236 }
Dan Austinf4865ca2015-10-21 11:28:59 -0700237
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700238 if (remain-- > 0) {
Dan Austinf4865ca2015-10-21 11:28:59 -0700239 const unsigned char val = *(pos+startIndex-index);
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700240 *c++ = makehexdigit(val>>4);
241 *c++ = makehexdigit(val);
242 } else if (!oneLine) {
243 *c++ = ' ';
244 *c++ = ' ';
245 }
246 } else {
247 if (remain > 0) {
248 if (index == 0 && word > 0) {
249 *c++ = ',';
250 *c++ = ' ';
251 }
252 if (index == 0) {
253 *c++ = '0';
254 *c++ = 'x';
255 }
Dan Austinf4865ca2015-10-21 11:28:59 -0700256 const unsigned char val = *(pos+startIndex-index);
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700257 *c++ = makehexdigit(val>>4);
258 *c++ = makehexdigit(val);
259 remain--;
260 }
261 }
262 }
Dan Austinf4865ca2015-10-21 11:28:59 -0700263
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700264 word += index;
265 }
266
267 if (!cStyle) {
268 remain = length;
269 *c++ = ' ';
270 *c++ = '\'';
271 for (index = 0; index < bytesPerLine; index++) {
272
273 if (remain-- > 0) {
274 const unsigned char val = pos[index];
275 *c++ = (val >= ' ' && val < 127) ? val : '.';
276 } else if (!oneLine) {
277 *c++ = ' ';
278 }
279 }
Dan Austinf4865ca2015-10-21 11:28:59 -0700280
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700281 *c++ = '\'';
282 if (length > bytesPerLine) *c++ = '\n';
283 } else {
284 if (remain > 0) *c++ = ',';
285 *c++ = '\n';
286 }
287
288 if (newLine && indent) func(cookie, stringForIndent(indent));
289 *c = 0;
290 func(cookie, buffer);
291 newLine = true;
Dan Austinf4865ca2015-10-21 11:28:59 -0700292
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700293 if (length <= bytesPerLine) break;
294 length -= bytesPerLine;
295 }
296
297 if (cStyle) {
298 if (indent > 0) func(cookie, stringForIndent(indent-1));
299 func(cookie, "};");
300 }
301}
302
Colin Crossdd6dafb2017-06-22 12:29:13 -0700303ssize_t getHWBinderKernelReferences(size_t count, uintptr_t* buf) {
304 sp<ProcessState> proc = ProcessState::selfOrNull();
Yi Kong55d41072018-07-23 14:55:39 -0700305 if (proc.get() == nullptr) {
Colin Crossdd6dafb2017-06-22 12:29:13 -0700306 return 0;
307 }
308
309 return proc->getKernelReferences(count, buf);
310}
311
Steven Moreland7173a4c2019-09-26 15:55:02 -0700312} // namespace hardware
313} // namespace android
Mathias Agopian4ea13dc2013-05-06 20:20:50 -0700314