• Home
  • History
  • Annotate
  • 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 <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  
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  
43  static void defaultPrintFunc(void* /*cookie*/, const char* txt)
44  {
45      printf("%s", txt);
46  }
47  
48  // ---------------------------------------------------------------------
49  
50  static inline int isident(int c)
51  {
52      return isalnum(c) || c == '_';
53  }
54  
55  static inline bool isasciitype(char c)
56  {
57      if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true;
58      return false;
59  }
60  
61  static inline char makehexdigit(uint32_t val)
62  {
63      return "0123456789abcdef"[val&0xF];
64  }
65  
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  
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  
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  
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  
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  
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