diff options
-rw-r--r-- | dexdump/dexdump.cc | 109 |
1 files changed, 74 insertions, 35 deletions
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc index e694c5f5ed..b6f31166f2 100644 --- a/dexdump/dexdump.cc +++ b/dexdump/dexdump.cc @@ -37,6 +37,8 @@ #include <inttypes.h> #include <stdio.h> +#include <cctype> +#include <iomanip> #include <memory> #include <sstream> #include <vector> @@ -45,6 +47,7 @@ #include "android-base/logging.h" #include "android-base/stringprintf.h" +#include "base/bit_utils.h" #include "dex/class_accessor-inl.h" #include "dex/code_item_accessors-inl.h" #include "dex/dex_file-inl.h" @@ -360,10 +363,10 @@ static void asciify(char* out, const unsigned char* data, size_t len) { /* * Dumps a string value with some escape characters. */ -static void dumpEscapedString(const char* p) { +static void dumpEscapedString(std::string_view p) { fputs("\"", gOutFile); - for (; *p; p++) { - switch (*p) { + for (char c : p) { + switch (c) { case '\\': fputs("\\\\", gOutFile); break; @@ -380,42 +383,78 @@ static void dumpEscapedString(const char* p) { fputs("\\r", gOutFile); break; default: - putc(*p, gOutFile); + putc(c, gOutFile); } // switch } // for fputs("\"", gOutFile); } +static size_t utf8Bytes(char start_byte) { + uint8_t sb = static_cast<uint8_t>(start_byte); + if ((sb & 0x80) == 0) { + return 1; + } + size_t msb = art::MostSignificantBit(static_cast<uint8_t>(~sb)); + CHECK_LE(7u - msb, 4u); + return 7 - msb; +} + /* * Dumps a string as an XML attribute value. */ -static void dumpXmlAttribute(const char* p) { - for (; *p; p++) { - switch (*p) { - case '&': - fputs("&", gOutFile); - break; - case '<': - fputs("<", gOutFile); - break; - case '>': - fputs(">", gOutFile); - break; - case '"': - fputs(""", gOutFile); - break; - case '\t': - fputs("	", gOutFile); - break; - case '\n': - fputs("
", gOutFile); - break; - case '\r': - fputs("
", gOutFile); - break; - default: - putc(*p, gOutFile); - } // switch +static void dumpXmlAttribute(std::string_view p) __attribute__((optnone)) { + for (const char* c = p.begin(); c < p.end(); ++c) { + if (std::isprint(*c)) { + switch (*c) { + case '&': + fputs("&", gOutFile); + break; + case '<': + fputs("<", gOutFile); + break; + case '>': + fputs(">", gOutFile); + break; + case '"': + fputs(""", gOutFile); + break; + case '\\': + fputs("\\\\", gOutFile); + break; + default: + putc(*c, gOutFile); + } // switch + } else { + uint32_t data = 0; + size_t remaining; + uint8_t uc = static_cast<uint8_t>(*c); + if (((uc) & 0x80) == 0) { + // Not a multi-byte char + data = static_cast<uint32_t>(*c); + remaining = 0; + } else if (utf8Bytes(uc) == 2) { + // 2 bytes + data = ((uc) & 0b00011111); + remaining = 1; + } else if (utf8Bytes(uc) == 3) { + // 3 bytes + data = ((uc) & 0b00001111); + remaining = 2; + } else { + // 4 bytes + CHECK_EQ(utf8Bytes(uc), 4u); + data = ((uc) & 0b00000111); + remaining = 3; + } + for (size_t i = 0; i < remaining; ++i) { + ++c; + data = data << 6; + uc = static_cast<uint8_t>(*c); + data |= static_cast<uint32_t>(uc & 0b00111111u); + } + // No good option so just use java encoding, too many chars are invalid + fprintf(gOutFile, "\\u%04x", data); + } } // for } @@ -478,9 +517,9 @@ static void dumpEncodedValue(const DexFile* pDexFile, const u1** data, u1 type, case DexFile::kDexAnnotationString: { const u4 idx = static_cast<u4>(readVarWidth(data, arg, false)); if (gOptions.outputFormat == OUTPUT_PLAIN) { - dumpEscapedString(pDexFile->StringDataByIdx(dex::StringIndex(idx))); + dumpEscapedString(pDexFile->StringViewByIdx(dex::StringIndex(idx))); } else { - dumpXmlAttribute(pDexFile->StringDataByIdx(dex::StringIndex(idx))); + dumpXmlAttribute(pDexFile->StringViewByIdx(dex::StringIndex(idx))); } break; } @@ -1666,7 +1705,7 @@ static void dumpMethodHandle(const DexFile* pDexFile, u4 idx) { fprintf(gOutFile, " target_class=\"%s\"\n", declaring_class); fprintf(gOutFile, " target_member=\"%s\"\n", member); fprintf(gOutFile, " target_member_type="); - dumpEscapedString(member_type.c_str()); + dumpEscapedString(member_type); fprintf(gOutFile, "\n>\n</method_handle>\n"); } } @@ -1786,7 +1825,7 @@ static void dumpCallSite(const DexFile* pDexFile, u4 idx) { fprintf(gOutFile, " link_argument[%zu] : %s (%s)\n", argument, value.c_str(), type); } else { fprintf(gOutFile, "<link_argument index=\"%zu\" type=\"%s\" value=", argument, type); - dumpEscapedString(value.c_str()); + dumpEscapedString(value); fprintf(gOutFile, "/>\n"); } |