diff options
author | Nico Rieck <nico.rieck@gmail.com> | 2014-02-22 16:12:20 +0000 |
---|---|---|
committer | Nico Rieck <nico.rieck@gmail.com> | 2014-02-22 16:12:20 +0000 |
commit | fa3089b14c9bfc86e7f937a70fa786aeb9abdfdd (patch) | |
tree | 1660c875d78562e9ee79bc2a0ebdb856f7e68c0a /lib/Object/COFFObjectFile.cpp | |
parent | 3c288fc8e72b8541a599c8396104988fe907499c (diff) | |
download | llvm-fa3089b14c9bfc86e7f937a70fa786aeb9abdfdd.tar.gz llvm-fa3089b14c9bfc86e7f937a70fa786aeb9abdfdd.tar.bz2 llvm-fa3089b14c9bfc86e7f937a70fa786aeb9abdfdd.tar.xz |
MC: Support COFF string tables larger than 10MB
Offsets past the range of single-slash encoding are encoded as base64,
padded to 6 characters, and prefixed with two slashes. This encoding is
undocumented but used by MSVC.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201940 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Object/COFFObjectFile.cpp')
-rw-r--r-- | lib/Object/COFFObjectFile.cpp | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index ed5494dc39..415b4cb0c1 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include <cctype> +#include <limits> using namespace llvm; using namespace object; @@ -52,6 +53,40 @@ static error_code getObject(const T *&Obj, const MemoryBuffer *M, return object_error::success; } +// Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without +// prefixed slashes. +static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { + assert(Str.size() <= 6 && "String too long, possible overflow."); + if (Str.size() > 6) + return true; + + uint64_t Value = 0; + while (!Str.empty()) { + unsigned CharVal; + if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 + CharVal = Str[0] - 'A'; + else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 + CharVal = Str[0] - 'a' + 26; + else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 + CharVal = Str[0] - '0' + 52; + else if (Str[0] == '+') // 62 + CharVal = Str[0] - '+' + 62; + else if (Str[0] == '/') // 63 + CharVal = Str[0] - '/' + 63; + else + return true; + + Value = (Value * 64) + CharVal; + Str = Str.substr(1); + } + + if (Value > std::numeric_limits<uint32_t>::max()) + return true; + + Result = static_cast<uint32_t>(Value); + return false; +} + const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Ref) const { const coff_symbol *Addr = reinterpret_cast<const coff_symbol*>(Ref.p); @@ -766,8 +801,13 @@ error_code COFFObjectFile::getSectionName(const coff_section *Sec, // Check for string table entry. First byte is '/'. if (Name[0] == '/') { uint32_t Offset; - if (Name.substr(1).getAsInteger(10, Offset)) - return object_error::parse_failed; + if (Name[1] == '/') { + if (decodeBase64StringEntry(Name.substr(2), Offset)) + return object_error::parse_failed; + } else { + if (Name.substr(1).getAsInteger(10, Offset)) + return object_error::parse_failed; + } if (error_code EC = getString(Offset, Name)) return EC; } |