Home | History | Annotate | Download | only in libhwbinder
      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 == NULL) func = defaultPrintFunc;
    170 
    171     size_t offset;
    172 
    173     unsigned char *pos = (unsigned char *)buf;
    174 
    175     if (pos == NULL) {
    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             const size_t startIndex = word+(alignment-(alignment?1:0));
    226 
    227             for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
    228 
    229                 if (!cStyle) {
    230                     if (index == 0 && word > 0 && alignment > 0) {
    231                         *c++ = ' ';
    232                     }
    233 
    234                     if (remain-- > 0) {
    235                         const unsigned char val = *(pos+startIndex-index);
    236                         *c++ = makehexdigit(val>>4);
    237                         *c++ = makehexdigit(val);
    238                     } else if (!oneLine) {
    239                         *c++ = ' ';
    240                         *c++ = ' ';
    241                     }
    242                 } else {
    243                     if (remain > 0) {
    244                         if (index == 0 && word > 0) {
    245                             *c++ = ',';
    246                             *c++ = ' ';
    247                         }
    248                         if (index == 0) {
    249                             *c++ = '0';
    250                             *c++ = 'x';
    251                         }
    252                         const unsigned char val = *(pos+startIndex-index);
    253                         *c++ = makehexdigit(val>>4);
    254                         *c++ = makehexdigit(val);
    255                         remain--;
    256                     }
    257                 }
    258             }
    259 
    260             word += index;
    261         }
    262 
    263         if (!cStyle) {
    264             remain = length;
    265             *c++ = ' ';
    266             *c++ = '\'';
    267             for (index = 0; index < bytesPerLine; index++) {
    268 
    269                 if (remain-- > 0) {
    270                     const unsigned char val = pos[index];
    271                     *c++ = (val >= ' ' && val < 127) ? val : '.';
    272                 } else if (!oneLine) {
    273                     *c++ = ' ';
    274                 }
    275             }
    276 
    277             *c++ = '\'';
    278             if (length > bytesPerLine) *c++ = '\n';
    279         } else {
    280             if (remain > 0) *c++ = ',';
    281             *c++ = '\n';
    282         }
    283 
    284         if (newLine && indent) func(cookie, stringForIndent(indent));
    285         *c = 0;
    286         func(cookie, buffer);
    287         newLine = true;
    288 
    289         if (length <= bytesPerLine) break;
    290         length -= bytesPerLine;
    291     }
    292 
    293     if (cStyle) {
    294         if (indent > 0) func(cookie, stringForIndent(indent-1));
    295         func(cookie, "};");
    296     }
    297 }
    298 
    299 ssize_t getHWBinderKernelReferences(size_t count, uintptr_t* buf) {
    300     sp<ProcessState> proc = ProcessState::selfOrNull();
    301     if (proc.get() == NULL) {
    302         return 0;
    303     }
    304 
    305     return proc->getKernelReferences(count, buf);
    306 }
    307 
    308 }; // namespace hardware
    309 }; // namespace android
    310 
    311