title: Where is the string table in a Windows DLL?
body: <p>I have written a routine to dump the symbols and sections from a DLL loaded with <code>LoadLibrary</code> but not sure how to decode MinGW DLLs that have section names that are longer than <code>IMAGE_SIZEOF_SHORT_NAME</code></p>
  
  <p>For example, a MinGW DLL outputs the follwing sections if I print them as strings:</p>
  
  <pre><code>[".text", ".data", ".rdata", ".pdata", ".xdata", ".bss", ".edata", ".idata",
   ".CRT", ".tls", ".reloc", "/4", "/19", "/31", "/45", "/57", "/70", "/81",
   "/92"]
  </code></pre>
  
  <p>The other sections as <code>objdump.exe</code> gets them:</p>
  
  <pre><code>.debug_aranges
  .debug_info
  .debug_abbrev
  .debug_line
  .debug_frame
  .debug_str
  .debug_loc
  .debug_ranges
  </code></pre>
  
  <p>Which are all longer than <code>IMAGE_SIZEOF_SHORT_NAME</code>.  <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms680341" rel="nofollow">MSDN</a> explains that:</p>
  
  <p><code>For longer names, this member contains a forward slash (/) followed by an ASCII representation of a decimal number that is an offset into the string table.</code></p>
  
  <p>So I have the following code:</p>
  
  <pre><code>  Char buffer[IMAGE_SIZEOF_SHORT_NAME + 1];
    std::strncpy(buffer, reinterpret_cast&lt;const Char * const&gt;(section_header_ptr[i].Name), IMAGE_SIZEOF_SHORT_NAME);
    buffer[IMAGE_SIZEOF_SHORT_NAME] = '\0';
    const Char * name = buffer;
    if (name[0] == '/') {
      const Long rva = std::strtol(name + 1, NULL, 10);
      if ((LONG_MAX == rva) || (LONG_MIN == rva) || ((0 == rva) &amp;&amp; (name[0] != '0'))) {
        static const Char * const failure = "failed to convert offset";
        name = failure;
      }
      // -- How do I get the string table here? and use the offset? --
    }
  </code></pre>
  
  <p>Reading the COFF spec I see that the string table is after the symbol entries so it should be</p>
  
  <pre><code>HMODULE handle = LoadLibrary("some_mingw_library.dll");
  PIMAGE_DOS_HEADER idh = (PIMAGE_DOS_HEADER)(handle);
  PIMAGE_NT_HEADERS inh = (PIMAGE_NT_HEADERS)(((const uint8_t*)(idh)) + idh-&gt;e_lfanew)
  PIMAGE_FILE_HEADER ifh = &amp;inh-&gt;FileHeader;
  PIMAGE_SYMBOL is = (PIMAGE_SYMBOL)(((const uint8_t*)(idh)) + ifh-&gt;PointerToSymbolTable)
  const char * const string_table = &amp;is[ifh-&gt;NumberOfSymbols];
  </code></pre>
  
  <p>But I get something that is definitely not the string table.  I can see the string table in my hex editor.  Where is the string table in a portable executable?</p>