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 <hwbinder/Debug.h>
18 #include <hwbinder/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 namespace hardware {
28 
29 // ---------------------------------------------------------------------
30 
31 static const char indentStr[] =
32 "                                                                            "
33 "                                                                            ";
34 
stringForIndent(int32_t indentLevel)35 const 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 
defaultPrintFunc(void *,const char * txt)43 static void defaultPrintFunc(void* /*cookie*/, const char* txt)
44 {
45     printf("%s", txt);
46 }
47 
48 // ---------------------------------------------------------------------
49 
isident(int c)50 static inline int isident(int c)
51 {
52     return isalnum(c) || c == '_';
53 }
54 
isasciitype(char c)55 static inline bool isasciitype(char c)
56 {
57     if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true;
58     return false;
59 }
60 
makehexdigit(uint32_t val)61 static inline char makehexdigit(uint32_t val)
62 {
63     return "0123456789abcdef"[val&0xF];
64 }
65 
appendhexnum(uint32_t val,char * out)66 static 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 
appendcharornum(char c,char * out,bool skipzero=true)75 static 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 
typetostring(uint32_t type,char * out,bool fullContext=true,bool strict=false)91 static 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     }
143 
144     if( fullContext ) {
145         *pos++ = '0';
146         *pos++ = 'x';
147     }
148     return appendhexnum(type, pos);
149 }
150 
printTypeCode(uint32_t typeCode,debugPrintFunc func,void * cookie)151 void 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 
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)159 void 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     }
169     if (func == nullptr) func = defaultPrintFunc;
170 
171     size_t offset;
172 
173     unsigned char *pos = (unsigned char *)buf;
174 
175     if (pos == nullptr) {
176         if (singleLineBytesCutoff < 0) func(cookie, "\n");
177         func(cookie, "(NULL)");
178         return;
179     }
180 
181     if (length == 0) {
182         if (singleLineBytesCutoff < 0) func(cookie, "\n");
183         func(cookie, "(empty)");
184         return;
185     }
186 
187     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     }
194 
195     char buffer[256];
196     static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1);
197 
198     if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine;
199 
200     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     }
210 
211     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;
222 
223         for (word = 0; word < bytesPerLine; ) {
224 
225             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;
230 
231             for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
232 
233                 if (!cStyle) {
234                     if (index == 0 && word > 0 && alignment > 0) {
235                         *c++ = ' ';
236                     }
237 
238                     if (remain-- > 0) {
239                         const unsigned char val = *(pos+startIndex-index);
240                         *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                         }
256                         const unsigned char val = *(pos+startIndex-index);
257                         *c++ = makehexdigit(val>>4);
258                         *c++ = makehexdigit(val);
259                         remain--;
260                     }
261                 }
262             }
263 
264             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             }
280 
281             *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;
292 
293         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 
getHWBinderKernelReferences(size_t count,uintptr_t * buf)303 ssize_t getHWBinderKernelReferences(size_t count, uintptr_t* buf) {
304     sp<ProcessState> proc = ProcessState::selfOrNull();
305     if (proc.get() == nullptr) {
306         return 0;
307     }
308 
309     return proc->getKernelReferences(count, buf);
310 }
311 
312 } // namespace hardware
313 } // namespace android
314 
315