1 /*
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
17 #include "Debug.h"
18
19 #include <binder/ProcessState.h>
20
21 #include <utils/misc.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <ctype.h>
26
27 namespace android {
28
hexString(const void * bytes,size_t len)29 std::string hexString(const void* bytes, size_t len) {
30 if (bytes == nullptr) return "<null>";
31
32 const uint8_t* bytes8 = static_cast<const uint8_t*>(bytes);
33 const char chars[] = "0123456789abcdef";
34 std::string result;
35 result.resize(len * 2);
36
37 for (size_t i = 0; i < len; i++) {
38 result[2 * i] = chars[bytes8[i] >> 4];
39 result[2 * i + 1] = chars[bytes8[i] & 0xf];
40 }
41
42 return result;
43 }
44
45 // ---------------------------------------------------------------------
46
47 static const char indentStr[] =
48 " "
49 " ";
50
stringForIndent(int32_t indentLevel)51 const char* stringForIndent(int32_t indentLevel)
52 {
53 ssize_t off = sizeof(indentStr)-1-(indentLevel*2);
54 return indentStr + (off < 0 ? 0 : off);
55 }
56
57 // ---------------------------------------------------------------------
58
defaultPrintFunc(void *,const char * txt)59 static void defaultPrintFunc(void* /*cookie*/, const char* txt)
60 {
61 printf("%s", txt);
62 }
63
64 // ---------------------------------------------------------------------
65
isident(int c)66 static inline int isident(int c)
67 {
68 return isalnum(c) || c == '_';
69 }
70
isasciitype(char c)71 static inline bool isasciitype(char c)
72 {
73 if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true;
74 return false;
75 }
76
makehexdigit(uint32_t val)77 static inline char makehexdigit(uint32_t val)
78 {
79 return "0123456789abcdef"[val&0xF];
80 }
81
appendhexnum(uint32_t val,char * out)82 static char* appendhexnum(uint32_t val, char* out)
83 {
84 for( int32_t i=28; i>=0; i-=4 ) {
85 *out++ = makehexdigit( val>>i );
86 }
87 *out = 0;
88 return out;
89 }
90
appendcharornum(char c,char * out,bool skipzero=true)91 static char* appendcharornum(char c, char* out, bool skipzero = true)
92 {
93 if (skipzero && c == 0) return out;
94
95 if (isasciitype(c)) {
96 *out++ = c;
97 return out;
98 }
99
100 *out++ = '\\';
101 *out++ = 'x';
102 *out++ = makehexdigit(c>>4);
103 *out++ = makehexdigit(c);
104 return out;
105 }
106
typetostring(uint32_t type,char * out,bool fullContext=true,bool strict=false)107 static char* typetostring(uint32_t type, char* out,
108 bool fullContext = true,
109 bool strict = false)
110 {
111 char* pos = out;
112 char c[4];
113 c[0] = (char)((type>>24)&0xFF);
114 c[1] = (char)((type>>16)&0xFF);
115 c[2] = (char)((type>>8)&0xFF);
116 c[3] = (char)(type&0xFF);
117 bool valid;
118 if( !strict ) {
119 // now even less strict!
120 // valid = isasciitype(c[3]);
121 valid = true;
122 int32_t i = 0;
123 bool zero = true;
124 while (valid && i<3) {
125 if (c[i] == 0) {
126 if (!zero) valid = false;
127 } else {
128 zero = false;
129 //if (!isasciitype(c[i])) valid = false;
130 }
131 i++;
132 }
133 // if all zeros, not a valid type code.
134 if (zero) valid = false;
135 } else {
136 valid = isident(c[3]) ? true : false;
137 int32_t i = 0;
138 bool zero = true;
139 while (valid && i<3) {
140 if (c[i] == 0) {
141 if (!zero) valid = false;
142 } else {
143 zero = false;
144 if (!isident(c[i])) valid = false;
145 }
146 i++;
147 }
148 }
149 if( valid && (!fullContext || c[0] != '0' || c[1] != 'x') ) {
150 if( fullContext ) *pos++ = '\'';
151 pos = appendcharornum(c[0], pos);
152 pos = appendcharornum(c[1], pos);
153 pos = appendcharornum(c[2], pos);
154 pos = appendcharornum(c[3], pos);
155 if( fullContext ) *pos++ = '\'';
156 *pos = 0;
157 return pos;
158 }
159
160 if( fullContext ) {
161 *pos++ = '0';
162 *pos++ = 'x';
163 }
164 return appendhexnum(type, pos);
165 }
166
printTypeCode(uint32_t typeCode,debugPrintFunc func,void * cookie)167 void printTypeCode(uint32_t typeCode, debugPrintFunc func, void* cookie)
168 {
169 char buffer[32];
170 char* end = typetostring(typeCode, buffer);
171 *end = 0;
172 func ? (*func)(cookie, buffer) : defaultPrintFunc(cookie, buffer);
173 }
174
printHexData(int32_t indent,const void * buf,size_t length,size_t bytesPerLine,int32_t singleLineBytesCutoff,size_t alignment,bool cStyle,debugPrintFunc func,void * cookie)175 void printHexData(int32_t indent, const void *buf, size_t length,
176 size_t bytesPerLine, int32_t singleLineBytesCutoff,
177 size_t alignment, bool cStyle,
178 debugPrintFunc func, void* cookie)
179 {
180 if (alignment == 0) {
181 if (bytesPerLine >= 16) alignment = 4;
182 else if (bytesPerLine >= 8) alignment = 2;
183 else alignment = 1;
184 }
185 if (func == nullptr) func = defaultPrintFunc;
186
187 size_t offset;
188
189 unsigned char *pos = (unsigned char *)buf;
190
191 if (pos == nullptr) {
192 if (singleLineBytesCutoff < 0) func(cookie, "\n");
193 func(cookie, "(NULL)");
194 return;
195 }
196
197 if (length == 0) {
198 if (singleLineBytesCutoff < 0) func(cookie, "\n");
199 func(cookie, "(empty)");
200 return;
201 }
202
203 if ((int32_t)length < 0) {
204 if (singleLineBytesCutoff < 0) func(cookie, "\n");
205 char buf[64];
206 sprintf(buf, "(bad length: %zu)", length);
207 func(cookie, buf);
208 return;
209 }
210
211 char buffer[256];
212 static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1);
213
214 if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine;
215
216 const bool oneLine = (int32_t)length <= singleLineBytesCutoff;
217 bool newLine = false;
218 if (cStyle) {
219 indent++;
220 func(cookie, "{\n");
221 newLine = true;
222 } else if (!oneLine) {
223 func(cookie, "\n");
224 newLine = true;
225 }
226
227 for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
228 ssize_t remain = length;
229
230 char* c = buffer;
231 if (!oneLine && !cStyle) {
232 sprintf(c, "0x%08x: ", (int)offset);
233 c += 12;
234 }
235
236 size_t index;
237 size_t word;
238
239 for (word = 0; word < bytesPerLine; ) {
240
241 size_t align_offset = alignment-(alignment?1:0);
242 if (remain > 0 && (size_t)remain <= align_offset) {
243 align_offset = remain - 1;
244 }
245 const size_t startIndex = word+align_offset;
246
247 for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
248
249 if (!cStyle) {
250 if (index == 0 && word > 0 && alignment > 0) {
251 *c++ = ' ';
252 }
253
254 if (remain-- > 0) {
255 const unsigned char val = *(pos+startIndex-index);
256 *c++ = makehexdigit(val>>4);
257 *c++ = makehexdigit(val);
258 } else if (!oneLine) {
259 *c++ = ' ';
260 *c++ = ' ';
261 }
262 } else {
263 if (remain > 0) {
264 if (index == 0 && word > 0) {
265 *c++ = ',';
266 *c++ = ' ';
267 }
268 if (index == 0) {
269 *c++ = '0';
270 *c++ = 'x';
271 }
272 const unsigned char val = *(pos+startIndex-index);
273 *c++ = makehexdigit(val>>4);
274 *c++ = makehexdigit(val);
275 remain--;
276 }
277 }
278 }
279
280 word += index;
281 }
282
283 if (!cStyle) {
284 remain = length;
285 *c++ = ' ';
286 *c++ = '\'';
287 for (index = 0; index < bytesPerLine; index++) {
288
289 if (remain-- > 0) {
290 const unsigned char val = pos[index];
291 *c++ = (val >= ' ' && val < 127) ? val : '.';
292 } else if (!oneLine) {
293 *c++ = ' ';
294 }
295 }
296
297 *c++ = '\'';
298 if (length > bytesPerLine) *c++ = '\n';
299 } else {
300 if (remain > 0) *c++ = ',';
301 *c++ = '\n';
302 }
303
304 if (newLine && indent) func(cookie, stringForIndent(indent));
305 *c = 0;
306 func(cookie, buffer);
307 newLine = true;
308
309 if (length <= bytesPerLine) break;
310 length -= bytesPerLine;
311 }
312
313 if (cStyle) {
314 if (indent > 0) func(cookie, stringForIndent(indent-1));
315 func(cookie, "};");
316 }
317 }
318
getBinderKernelReferences(size_t count,uintptr_t * buf)319 ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf) {
320 sp<ProcessState> proc = ProcessState::selfOrNull();
321 if (proc.get() == nullptr) {
322 return 0;
323 }
324
325 return proc->getKernelReferences(count, buf);
326 }
327
328 } // namespace android
329
330