You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
310 lines
8.3 KiB
310 lines
8.3 KiB
/* |
|
* Copyright (C) 2005 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#include <hwbinder/Debug.h> |
|
#include <hwbinder/ProcessState.h> |
|
|
|
#include <utils/misc.h> |
|
|
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <ctype.h> |
|
|
|
namespace android { |
|
namespace hardware { |
|
|
|
// --------------------------------------------------------------------- |
|
|
|
static const char indentStr[] = |
|
" " |
|
" "; |
|
|
|
const char* stringForIndent(int32_t indentLevel) |
|
{ |
|
ssize_t off = sizeof(indentStr)-1-(indentLevel*2); |
|
return indentStr + (off < 0 ? 0 : off); |
|
} |
|
|
|
// --------------------------------------------------------------------- |
|
|
|
static void defaultPrintFunc(void* /*cookie*/, const char* txt) |
|
{ |
|
printf("%s", txt); |
|
} |
|
|
|
// --------------------------------------------------------------------- |
|
|
|
static inline int isident(int c) |
|
{ |
|
return isalnum(c) || c == '_'; |
|
} |
|
|
|
static inline bool isasciitype(char c) |
|
{ |
|
if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true; |
|
return false; |
|
} |
|
|
|
static inline char makehexdigit(uint32_t val) |
|
{ |
|
return "0123456789abcdef"[val&0xF]; |
|
} |
|
|
|
static char* appendhexnum(uint32_t val, char* out) |
|
{ |
|
for( int32_t i=28; i>=0; i-=4 ) { |
|
*out++ = makehexdigit( val>>i ); |
|
} |
|
*out = 0; |
|
return out; |
|
} |
|
|
|
static char* appendcharornum(char c, char* out, bool skipzero = true) |
|
{ |
|
if (skipzero && c == 0) return out; |
|
|
|
if (isasciitype(c)) { |
|
*out++ = c; |
|
return out; |
|
} |
|
|
|
*out++ = '\\'; |
|
*out++ = 'x'; |
|
*out++ = makehexdigit(c>>4); |
|
*out++ = makehexdigit(c); |
|
return out; |
|
} |
|
|
|
static char* typetostring(uint32_t type, char* out, |
|
bool fullContext = true, |
|
bool strict = false) |
|
{ |
|
char* pos = out; |
|
char c[4]; |
|
c[0] = (char)((type>>24)&0xFF); |
|
c[1] = (char)((type>>16)&0xFF); |
|
c[2] = (char)((type>>8)&0xFF); |
|
c[3] = (char)(type&0xFF); |
|
bool valid; |
|
if( !strict ) { |
|
// now even less strict! |
|
// valid = isasciitype(c[3]); |
|
valid = true; |
|
int32_t i = 0; |
|
bool zero = true; |
|
while (valid && i<3) { |
|
if (c[i] == 0) { |
|
if (!zero) valid = false; |
|
} else { |
|
zero = false; |
|
//if (!isasciitype(c[i])) valid = false; |
|
} |
|
i++; |
|
} |
|
// if all zeros, not a valid type code. |
|
if (zero) valid = false; |
|
} else { |
|
valid = isident(c[3]) ? true : false; |
|
int32_t i = 0; |
|
bool zero = true; |
|
while (valid && i<3) { |
|
if (c[i] == 0) { |
|
if (!zero) valid = false; |
|
} else { |
|
zero = false; |
|
if (!isident(c[i])) valid = false; |
|
} |
|
i++; |
|
} |
|
} |
|
if( valid && (!fullContext || c[0] != '0' || c[1] != 'x') ) { |
|
if( fullContext ) *pos++ = '\''; |
|
pos = appendcharornum(c[0], pos); |
|
pos = appendcharornum(c[1], pos); |
|
pos = appendcharornum(c[2], pos); |
|
pos = appendcharornum(c[3], pos); |
|
if( fullContext ) *pos++ = '\''; |
|
*pos = 0; |
|
return pos; |
|
} |
|
|
|
if( fullContext ) { |
|
*pos++ = '0'; |
|
*pos++ = 'x'; |
|
} |
|
return appendhexnum(type, pos); |
|
} |
|
|
|
void printTypeCode(uint32_t typeCode, debugPrintFunc func, void* cookie) |
|
{ |
|
char buffer[32]; |
|
char* end = typetostring(typeCode, buffer); |
|
*end = 0; |
|
func ? (*func)(cookie, buffer) : defaultPrintFunc(cookie, buffer); |
|
} |
|
|
|
void 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) |
|
{ |
|
if (alignment == 0) { |
|
if (bytesPerLine >= 16) alignment = 4; |
|
else if (bytesPerLine >= 8) alignment = 2; |
|
else alignment = 1; |
|
} |
|
if (func == NULL) func = defaultPrintFunc; |
|
|
|
size_t offset; |
|
|
|
unsigned char *pos = (unsigned char *)buf; |
|
|
|
if (pos == NULL) { |
|
if (singleLineBytesCutoff < 0) func(cookie, "\n"); |
|
func(cookie, "(NULL)"); |
|
return; |
|
} |
|
|
|
if (length == 0) { |
|
if (singleLineBytesCutoff < 0) func(cookie, "\n"); |
|
func(cookie, "(empty)"); |
|
return; |
|
} |
|
|
|
if ((int32_t)length < 0) { |
|
if (singleLineBytesCutoff < 0) func(cookie, "\n"); |
|
char buf[64]; |
|
sprintf(buf, "(bad length: %zu)", length); |
|
func(cookie, buf); |
|
return; |
|
} |
|
|
|
char buffer[256]; |
|
static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1); |
|
|
|
if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine; |
|
|
|
const bool oneLine = (int32_t)length <= singleLineBytesCutoff; |
|
bool newLine = false; |
|
if (cStyle) { |
|
indent++; |
|
func(cookie, "{\n"); |
|
newLine = true; |
|
} else if (!oneLine) { |
|
func(cookie, "\n"); |
|
newLine = true; |
|
} |
|
|
|
for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) { |
|
long remain = length; |
|
|
|
char* c = buffer; |
|
if (!oneLine && !cStyle) { |
|
sprintf(c, "0x%08x: ", (int)offset); |
|
c += 12; |
|
} |
|
|
|
size_t index; |
|
size_t word; |
|
|
|
for (word = 0; word < bytesPerLine; ) { |
|
|
|
const size_t startIndex = word+(alignment-(alignment?1:0)); |
|
|
|
for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) { |
|
|
|
if (!cStyle) { |
|
if (index == 0 && word > 0 && alignment > 0) { |
|
*c++ = ' '; |
|
} |
|
|
|
if (remain-- > 0) { |
|
const unsigned char val = *(pos+startIndex-index); |
|
*c++ = makehexdigit(val>>4); |
|
*c++ = makehexdigit(val); |
|
} else if (!oneLine) { |
|
*c++ = ' '; |
|
*c++ = ' '; |
|
} |
|
} else { |
|
if (remain > 0) { |
|
if (index == 0 && word > 0) { |
|
*c++ = ','; |
|
*c++ = ' '; |
|
} |
|
if (index == 0) { |
|
*c++ = '0'; |
|
*c++ = 'x'; |
|
} |
|
const unsigned char val = *(pos+startIndex-index); |
|
*c++ = makehexdigit(val>>4); |
|
*c++ = makehexdigit(val); |
|
remain--; |
|
} |
|
} |
|
} |
|
|
|
word += index; |
|
} |
|
|
|
if (!cStyle) { |
|
remain = length; |
|
*c++ = ' '; |
|
*c++ = '\''; |
|
for (index = 0; index < bytesPerLine; index++) { |
|
|
|
if (remain-- > 0) { |
|
const unsigned char val = pos[index]; |
|
*c++ = (val >= ' ' && val < 127) ? val : '.'; |
|
} else if (!oneLine) { |
|
*c++ = ' '; |
|
} |
|
} |
|
|
|
*c++ = '\''; |
|
if (length > bytesPerLine) *c++ = '\n'; |
|
} else { |
|
if (remain > 0) *c++ = ','; |
|
*c++ = '\n'; |
|
} |
|
|
|
if (newLine && indent) func(cookie, stringForIndent(indent)); |
|
*c = 0; |
|
func(cookie, buffer); |
|
newLine = true; |
|
|
|
if (length <= bytesPerLine) break; |
|
length -= bytesPerLine; |
|
} |
|
|
|
if (cStyle) { |
|
if (indent > 0) func(cookie, stringForIndent(indent-1)); |
|
func(cookie, "};"); |
|
} |
|
} |
|
|
|
ssize_t getHWBinderKernelReferences(size_t count, uintptr_t* buf) { |
|
sp<ProcessState> proc = ProcessState::selfOrNull(); |
|
if (proc.get() == NULL) { |
|
return 0; |
|
} |
|
|
|
return proc->getKernelReferences(count, buf); |
|
} |
|
|
|
}; // namespace hardware |
|
}; // namespace android |
|
|
|
|