<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Feb 22, 2014 at 8:12 AM, Nico Rieck <span dir="ltr"><<a href="mailto:nico.rieck@gmail.com" target="_blank">nico.rieck@gmail.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: nrieck<br>
Date: Sat Feb 22 10:12:20 2014<br>
New Revision: 201940<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=201940&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=201940&view=rev</a><br>
Log:<br>
MC: Support COFF string tables larger than 10MB<br>
<br>
Offsets past the range of single-slash encoding are encoded as base64,<br>
padded to 6 characters, and prefixed with two slashes. This encoding is<br>
undocumented but used by MSVC.<br>
<br>
Modified:<br>
    llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp<br>
    llvm/trunk/lib/Object/COFFObjectFile.cpp<br>
    llvm/trunk/test/MC/COFF/section-name-encoding.s<br>
<br>
Modified: llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp?rev=201940&r1=201939&r2=201940&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp?rev=201940&r1=201939&r2=201940&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp (original)<br>
+++ llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp Sat Feb 22 10:12:20 2014<br>
@@ -468,12 +468,35 @@ void WinCOFFObjectWriter::DefineSymbol(M<br>
   }<br>
 }<br>
<br>
+// Encode a string table entry offset in base 64, padded to 6 chars, and<br>
+// prefixed with a double slash: '//AAAAAA', '//AAAAAB', ...<br>
+// Buffer must be at least 8 bytes large. No terminating null appended.<br>
+static void encodeBase64StringEntry(char* Buffer, uint64_t Value) {<br>
+  assert(Value > 9999999 && Value <= 0xFFFFFFFFF &&<br>
+         "Illegal section name encoding for value");<br>
+<br>
+  static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"<br>
+                                 "abcdefghijklmnopqrstuvwxyz"<br>
+                                 "0123456789+/";<br>
+<br>
+  Buffer[0] = '/';<br>
+  Buffer[1] = '/';<br>
+<br>
+  char* Ptr = Buffer + 7;<br>
+  for (unsigned i = 0; i < 6; ++i) {<br>
+    unsigned Rem = Value % 64;<br>
+    Value /= 64;<br>
+    *(Ptr--) = Alphabet[Rem];<br>
+  }<br>
+}<br>
+<br>
 /// making a section real involves assigned it a number and putting<br>
 /// name into the string table if needed<br>
 void WinCOFFObjectWriter::MakeSectionReal(COFFSection &S, size_t Number) {<br>
   if (S.Name.size() > COFF::NameSize) {<br>
     const unsigned Max6DecimalSize = 999999;<br>
     const unsigned Max7DecimalSize = 9999999;<br>
+    const uint64_t MaxBase64Size = 0xFFFFFFFFF; // 64^6, including 0<br>
     uint64_t StringTableEntry = Strings.insert(S.Name.c_str());<br>
<br>
     if (StringTableEntry <= Max6DecimalSize) {<br>
@@ -484,8 +507,11 @@ void WinCOFFObjectWriter::MakeSectionRea<br>
       char buffer[9] = { };<br>
       std::sprintf(buffer, "/%d", unsigned(StringTableEntry));<br>
       std::memcpy(<a href="http://S.Header.Name" target="_blank">S.Header.Name</a>, buffer, 8);<br>
+    } else if (StringTableEntry <= MaxBase64Size) {<br>
+      // Starting with 10,000,000, offsets are encoded as base64.<br>
+      encodeBase64StringEntry(<a href="http://S.Header.Name" target="_blank">S.Header.Name</a>, StringTableEntry);<br>
     } else {<br>
-      report_fatal_error("COFF string table is greater than 9,999,999 bytes.");<br>
+      report_fatal_error("COFF string table is greater than 64 GB.");<br>
     }<br>
   } else<br>
     std::memcpy(<a href="http://S.Header.Name" target="_blank">S.Header.Name</a>, S.Name.c_str(), S.Name.size());<br>
<br>
Modified: llvm/trunk/lib/Object/COFFObjectFile.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/COFFObjectFile.cpp?rev=201940&r1=201939&r2=201940&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/COFFObjectFile.cpp?rev=201940&r1=201939&r2=201940&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Object/COFFObjectFile.cpp (original)<br>
+++ llvm/trunk/lib/Object/COFFObjectFile.cpp Sat Feb 22 10:12:20 2014<br>
@@ -19,6 +19,7 @@<br>
 #include "llvm/Support/Debug.h"<br>
 #include "llvm/Support/raw_ostream.h"<br>
 #include <cctype><br>
+#include <limits><br>
<br>
 using namespace llvm;<br>
 using namespace object;<br>
@@ -52,6 +53,40 @@ static error_code getObject(const T *&Ob<br>
   return object_error::success;<br>
 }<br>
<br>
+// Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without<br>
+// prefixed slashes.<br>
+static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {<br>
+  assert(Str.size() <= 6 && "String too long, possible overflow.");<br>
+  if (Str.size() > 6)<br>
+    return true;<br>
+<br>
+  uint64_t Value = 0;<br>
+  while (!Str.empty()) {<br>
+    unsigned CharVal;<br>
+    if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25<br>
+      CharVal = Str[0] - 'A';<br>
+    else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51<br>
+      CharVal = Str[0] - 'a' + 26;<br>
+    else if (Str[0] >= '0' && Str[0] <= '9') // 52..61<br>
+      CharVal = Str[0] - '0' + 52;<br>
+    else if (Str[0] == '+') // 62<br>
+      CharVal = Str[0] - '+' + 62;<br></blockquote><div><br></div><div>Is this line equivalent to "CharVal = 62;"?</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


+    else if (Str[0] == '/') // 63<br>
+      CharVal = Str[0] - '/' + 63;<br></blockquote><div><br></div><div>Ditto</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    else<br>
+      return true;<br>
+<br>
+    Value = (Value * 64) + CharVal;<br>
+    Str = Str.substr(1);<br>
+  }<br>
+<br>
+  if (Value > std::numeric_limits<uint32_t>::max())<br>
+    return true;<br>
+<br>
+  Result = static_cast<uint32_t>(Value);<br>
+  return false;<br>
+}<br>
+<br>
 const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Ref) const {<br>
   const coff_symbol *Addr = reinterpret_cast<const coff_symbol*>(Ref.p);<br>
<br>
@@ -766,8 +801,13 @@ error_code COFFObjectFile::getSectionNam<br>
   // Check for string table entry. First byte is '/'.<br>
   if (Name[0] == '/') {<br>
     uint32_t Offset;<br>
-    if (Name.substr(1).getAsInteger(10, Offset))<br>
-      return object_error::parse_failed;<br>
+    if (Name[1] == '/') {<br>
+      if (decodeBase64StringEntry(Name.substr(2), Offset))<br>
+        return object_error::parse_failed;<br>
+    } else {<br>
+      if (Name.substr(1).getAsInteger(10, Offset))<br>
+        return object_error::parse_failed;<br>
+    }<br>
     if (error_code EC = getString(Offset, Name))<br>
       return EC;<br>
   }<br>
<br>
Modified: llvm/trunk/test/MC/COFF/section-name-encoding.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/section-name-encoding.s?rev=201940&r1=201939&r2=201940&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/section-name-encoding.s?rev=201940&r1=201939&r2=201940&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/test/MC/COFF/section-name-encoding.s (original)<br>
+++ llvm/trunk/test/MC/COFF/section-name-encoding.s Sat Feb 22 10:12:20 2014<br>
@@ -3,6 +3,7 @@<br>
 // Encodings for different lengths:<br>
 //   [0, 8]:               raw name<br>
 //   (8, 999999]:          base 10 string table index (/9999999)<br>
+//   (999999, 0xFFFFFFFF]: base 64 string table index (//AAAAAA)<br>
 //<br>
 // RUN: llvm-mc -triple x86_64-pc-win32 -filetype=obj %s | llvm-readobj -s | FileCheck %s<br>
<br>
@@ -60,3 +61,28 @@ pad_sections aaaaaaaaaaaaaaaaaaaaaaaaaaa<br>
 // CHECK:     Name: seven_digit (2F 31 30 30 30 30 32 39)<br>
 // CHECK:   }<br>
 .section seven_digit; .long 1<br>
+<br>
+<br>
+// Generate padding sections to increase the string table size to at least<br>
+// 10,000,000 bytes.<br>
+.macro pad_sections_ex pad<br>
+  // 9x \pad<br>
+  pad_sections \pad\pad\pad\pad\pad\pad\pad\pad\pad<br>
+.endm<br>
+<br>
+// 1000x 'a'<br>
+pad_sections_ex aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!<br>


 aaaaaaaaa<br>
 aaaaaaaaaaaaaaaaaaa<br>
+<br>
+<br>
+// //AAmJa4 == 1000029 + 12 + (5 * (2 + (9 * 20 * 10 * 1000) + 1)) == 38*64^3 + 9*64^2 + 26*64 + 56<br>
+//             v         |     |    v    ~~~~~~~~~~~~~~~~~~    v<br>
+// seven_digit offset    v     v   "p0"         pad            NUL seperator<br>
+//         "seven_digit\0"     # of pad sections<br>
+//<br>
+// "2F 2F 41 41 6D 4A 61 34" is "//AAmJa4", which decodes to "0 0 38 9 26 56".<br>
+//<br>
+// CHECK:   Section {<br>
+// CHECK:     Number: 15<br>
+// CHECK:     Name: double_slash (2F 2F 41 41 6D 4A 61 34)<br>
+// CHECK:   }<br>
+.section double_slash; .long 1<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>