diff options
Diffstat (limited to 'runtime/base/hex_dump.cc')
-rw-r--r-- | runtime/base/hex_dump.cc | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/runtime/base/hex_dump.cc b/runtime/base/hex_dump.cc new file mode 100644 index 0000000..936c52b --- /dev/null +++ b/runtime/base/hex_dump.cc @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2014 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 "hex_dump.h" + +#include "globals.h" + +#include <string.h> + +namespace art { + +void HexDump::Dump(std::ostream& os) const { + if (byte_count_ == 0) { + return; + } + + if (address_ == NULL) { + os << "00000000:"; + return; + } + + static const char gHexDigit[] = "0123456789abcdef"; + const unsigned char* addr = reinterpret_cast<const unsigned char*>(address_); + // 01234560: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef + char out[(kBitsPerWord / 4) + /* offset */ + 1 + /* colon */ + (16 * 3) + /* 16 hex digits and space */ + 2 + /* white space */ + 16 + /* 16 characters*/ + 1 /* \0 */ ]; + size_t offset; /* offset to show while printing */ + + if (show_actual_addresses_) { + offset = reinterpret_cast<size_t>(addr); + } else { + offset = 0; + } + memset(out, ' ', sizeof(out)-1); + out[kBitsPerWord / 4] = ':'; + out[sizeof(out)-1] = '\0'; + + size_t byte_count = byte_count_; + size_t gap = offset & 0x0f; + while (byte_count > 0) { + size_t line_offset = offset & ~0x0f; + + char* hex = out; + char* asc = out + (kBitsPerWord / 4) + /* offset */ 1 + /* colon */ + (16 * 3) + /* 16 hex digits and space */ 2 /* white space */; + + for (int i = 0; i < (kBitsPerWord / 4); i++) { + *hex++ = gHexDigit[line_offset >> (kBitsPerWord - 4)]; + line_offset <<= 4; + } + hex++; + hex++; + + size_t count = std::min(byte_count, 16 - gap); + // CHECK_NE(count, 0U); + // CHECK_LE(count + gap, 16U); + + if (gap) { + /* only on first line */ + hex += gap * 3; + asc += gap; + } + + size_t i; + for (i = gap ; i < count + gap; i++) { + *hex++ = gHexDigit[*addr >> 4]; + *hex++ = gHexDigit[*addr & 0x0f]; + hex++; + if (*addr >= 0x20 && *addr < 0x7f /*isprint(*addr)*/) { + *asc++ = *addr; + } else { + *asc++ = '.'; + } + addr++; + } + for (; i < 16; i++) { + /* erase extra stuff; only happens on last line */ + *hex++ = ' '; + *hex++ = ' '; + hex++; + *asc++ = ' '; + } + + os << prefix_ << out; + + gap = 0; + byte_count -= count; + offset += count; + if (byte_count > 0) { + os << "\n"; + } + } +} + +} // namespace art |