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