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 26namespace android { 27 28// --------------------------------------------------------------------- 29 30static const char indentStr[] = 31" " 32" "; 33 34const 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 42static void defaultPrintFunc(void* /*cookie*/, const char* txt) 43{ 44 printf("%s", txt); 45} 46 47// --------------------------------------------------------------------- 48 49static inline int isident(int c) 50{ 51 return isalnum(c) || c == '_'; 52} 53 54static inline bool isasciitype(char c) 55{ 56 if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true; 57 return false; 58} 59 60static inline char makehexdigit(uint32_t val) 61{ 62 return "0123456789abcdef"[val&0xF]; 63} 64 65static 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 74static 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 90static 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 150void 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 158void 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 298ssize_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