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