Quick fixes to the PE COFF file loader.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@139448 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 37afed7..425c668 100644
--- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -72,6 +72,46 @@
 #define IMAGE_FILE_UP_SYSTEM_ONLY           0x4000
 #define IMAGE_FILE_BYTES_REVERSED_HI        0x8000
 
+
+// Section Flags
+// The section flags in the Characteristics field of the section header indicate
+// characteristics of the section.
+#define IMAGE_SCN_TYPE_NO_PAD               0x00000008 // The section should not be padded to the next boundary. This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files.
+#define IMAGE_SCN_CNT_CODE                  0x00000020 // The section contains executable code.
+#define IMAGE_SCN_CNT_INITIALIZED_DATA      0x00000040 // The section contains initialized data.
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA    0x00000080 // The section contains uninitialized data.
+#define IMAGE_SCN_LNK_OTHER                 0x00000100 // Reserved for future use.
+#define IMAGE_SCN_LNK_INFO                  0x00000200 // The section contains comments or other information. The .drectve section has this type. This is valid for object files only.
+#define IMAGE_SCN_LNK_REMOVE                0x00000800 // The section will not become part of the image. This is valid only for object files.
+#define IMAGE_SCN_LNK_COMDAT                0x00001000 // The section contains COMDAT data. For more information, see section 5.5.6, “COMDAT Sections (Object Only).” This is valid only for object files.
+#define IMAGE_SCN_GPREL                     0x00008000 // The section contains data referenced through the global pointer (GP).
+#define IMAGE_SCN_MEM_PURGEABLE             0x00020000
+#define IMAGE_SCN_MEM_16BIT                 0x00020000 // For ARM machine types, the section contains Thumb code.  Reserved for future use with other machine types.
+#define IMAGE_SCN_MEM_LOCKED                0x00040000
+#define IMAGE_SCN_MEM_PRELOAD               0x00080000
+#define IMAGE_SCN_ALIGN_1BYTES              0x00100000 // Align data on a 1-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_2BYTES              0x00200000 // Align data on a 2-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_4BYTES              0x00300000 // Align data on a 4-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_8BYTES              0x00400000 // Align data on an 8-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_16BYTES             0x00500000 // Align data on a 16-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_32BYTES             0x00600000 // Align data on a 32-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_64BYTES             0x00700000 // Align data on a 64-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_128BYTES            0x00800000 // Align data on a 128-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_256BYTES            0x00900000 // Align data on a 256-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_512BYTES            0x00A00000 // Align data on a 512-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_1024BYTES           0x00B00000 // Align data on a 1024-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_2048BYTES           0x00C00000 // Align data on a 2048-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_4096BYTES           0x00D00000 // Align data on a 4096-byte boundary. Valid only for object files.
+#define IMAGE_SCN_ALIGN_8192BYTES           0x00E00000 // Align data on an 8192-byte boundary. Valid only for object files.
+#define IMAGE_SCN_LNK_NRELOC_OVFL           0x01000000 // The section contains extended relocations.
+#define IMAGE_SCN_MEM_DISCARDABLE           0x02000000 // The section can be discarded as needed.
+#define IMAGE_SCN_MEM_NOT_CACHED            0x04000000 // The section cannot be cached.
+#define IMAGE_SCN_MEM_NOT_PAGED             0x08000000 // The section is not pageable.
+#define IMAGE_SCN_MEM_SHARED                0x10000000 // The section can be shared in memory.
+#define IMAGE_SCN_MEM_EXECUTE               0x20000000 // The section can be executed as code.
+#define IMAGE_SCN_MEM_READ                  0x40000000 // The section can be read.
+#define IMAGE_SCN_MEM_WRITE                 0x80000000 // The section can be written to.
+
 using namespace lldb;
 using namespace lldb_private;
 
@@ -162,12 +202,14 @@
         uint32_t pe_signature = m_data.GetU32 (&offset);
         if (pe_signature != IMAGE_NT_SIGNATURE)
             return false;
-    }
-    if (ParseCOFFHeader(&offset))
-    {
-        if (m_coff_header.hdrsize > 0)
-            ParseCOFFOptionalHeader(&offset);
-        ParseSectionHeaders (offset);
+        if (ParseCOFFHeader(&offset))
+        {
+            if (m_coff_header.hdrsize > 0)
+                ParseCOFFOptionalHeader(&offset);
+            ParseSectionHeaders (offset);
+        }
+        StreamFile s(stdout, false);// REMOVE THIS LINE!!!
+        Dump(&s);// REMOVE THIS LINE!!!
         return true;
     }
     return false;
@@ -334,7 +376,7 @@
                 m_coff_header_opt.reserved1                     = m_data.GetU32(offset_ptr); 
                 m_coff_header_opt.image_size                    = m_data.GetU32(offset_ptr); 
                 m_coff_header_opt.header_size                   = m_data.GetU32(offset_ptr); 
-                m_coff_header_opt.checksym                      = m_data.GetU32(offset_ptr); 
+                m_coff_header_opt.checksum                      = m_data.GetU32(offset_ptr); 
                 m_coff_header_opt.subsystem                     = m_data.GetU16(offset_ptr); 
                 m_coff_header_opt.dll_flags                     = m_data.GetU16(offset_ptr); 
                 m_coff_header_opt.stack_reserve_size            = m_data.GetMaxU64 (offset_ptr, addr_byte_size);
@@ -436,39 +478,57 @@
         SectionList *sect_list = GetSectionList();
         m_symtab_ap.reset(new Symtab(this));
         Mutex::Locker symtab_locker (m_symtab_ap->GetMutex());
-        DataExtractor stab_data;
-        DataExtractor stabstr_data;
-        static ConstString g_stab_sect_name(".stab");
-        static ConstString g_stabstr_sect_name(".stabstr");
-        const Section *stab_section = sect_list->FindSectionByName (g_stab_sect_name).get();
-        if (stab_section == NULL)
-            return m_symtab_ap.get();
-        const Section *stabstr_section = sect_list->FindSectionByName (g_stabstr_sect_name).get();
-        if (stabstr_section == NULL)
-            return m_symtab_ap.get();
-        uint32_t offset = 0;
-        if (stab_section->ReadSectionDataFromObjectFile (this, stab_data) &&
-            stabstr_section->ReadSectionDataFromObjectFile (this, stabstr_data))
+        
+        const uint32_t num_syms = m_coff_header.nsyms;
+
+        if (num_syms > 0 && m_coff_header.symoff > 0)
         {
-            const uint32_t num_syms = stab_data.GetByteSize() / sizeof (coff_symbol_t);
+            const uint32_t symbol_size = sizeof(section_header_t);
+            const uint32_t addr_byte_size = GetAddressByteSize ();
+            const size_t symbol_data_size = num_syms * symbol_size; 
+            // Include the 4 bytes string table size at the end of the symbols
+            DataBufferSP symtab_data_sp(m_file.ReadFileContents (m_coff_header.symoff, symbol_data_size + 4));
+            DataExtractor symtab_data (symtab_data_sp, GetByteOrder(), addr_byte_size);
+            uint32_t offset = symbol_data_size;
+            const uint32_t strtab_size = symtab_data.GetU32 (&offset);
+            DataBufferSP strtab_data_sp(m_file.ReadFileContents (m_coff_header.symoff + symbol_data_size + 4, strtab_size));
+            DataExtractor strtab_data (strtab_data_sp, GetByteOrder(), addr_byte_size);
+
+            offset = 0;
+            std::string symbol_name;
             Symbol *symbols = m_symtab_ap->Resize (num_syms);
             for (uint32_t i=0; i<num_syms; ++i)
             {
                 coff_symbol_t symbol;
-                const void *name_data = stab_data.GetData(&offset, sizeof(symbol.name));
-                
-                if (name_data == NULL)
-                    break;
-                memcpy (symbol.name, name_data, sizeof(symbol.name));
-                symbol.value = stab_data.GetU32 (&offset);
-                symbol.sect = stab_data.GetU16 (&offset);
-                symbol.type = stab_data.GetU16 (&offset);
-                symbol.storage = stab_data.GetU8 (&offset);
-                symbol.naux = stab_data.GetU8 (&offset);		
-
-                symbol.name[sizeof(symbol.name)-1] = '\0';
+                const uint32_t symbol_offset = offset;
+                const char *symbol_name_cstr = NULL;
+                // If the first 4 bytes of the symbol string are zero, then we
+                // it is followed by a 4 byte string table offset. Else these
+                // 8 bytes contain the symbol name
+                if (symtab_data.GetU32 (&offset) == 0)
+                {
+                    // Long string that doesn't fit into the symbol table name,
+                    // so now we must read the 4 byte string table offset
+                    uint32_t strtab_offset = symtab_data.GetU32 (&offset);
+                    symbol_name_cstr = strtab_data.PeekCStr (strtab_offset);
+                    symbol_name.assign (symbol_name_cstr);
+                }
+                else
+                {
+                    // Short string that fits into the symbol table name which is 8 bytes
+                    offset += sizeof(symbol.name) - 4; // Skip remaining 
+                    symbol_name_cstr = symtab_data.PeekCStr (symbol_offset);
+                    if (symbol_name_cstr == NULL)
+                        break;
+                    symbol_name.assign (symbol_name_cstr, sizeof(symbol.name));
+                }
+                symbol.value    = symtab_data.GetU32 (&offset);
+                symbol.sect     = symtab_data.GetU16 (&offset);
+                symbol.type     = symtab_data.GetU16 (&offset);
+                symbol.storage  = symtab_data.GetU8  (&offset);
+                symbol.naux     = symtab_data.GetU8  (&offset);		
                 Address symbol_addr(sect_list->GetSectionAtIndex(symbol.sect-1).get(), symbol.value);
-                symbols[i].GetMangled ().SetValue(symbol.name, symbol.name[0]=='_' && symbol.name[1] == 'Z');
+                symbols[i].GetMangled ().SetValue (symbol_name.c_str(), symbol_name[0]=='_' && symbol_name[1] == 'Z');
                 symbols[i].SetValue(symbol_addr);
 
                 if (symbol.naux > 0)
@@ -495,14 +555,70 @@
             std::string sect_name;
             GetSectionName (sect_name, m_sect_headers[idx]);
             ConstString const_sect_name (sect_name.c_str());
-            
+            static ConstString g_code_sect_name (".code");
+            static ConstString g_CODE_sect_name ("CODE");
+            static ConstString g_data_sect_name (".data");
+            static ConstString g_DATA_sect_name ("DATA");
+            static ConstString g_bss_sect_name (".bss");
+            static ConstString g_BSS_sect_name ("BSS");
+            static ConstString g_debug_sect_name (".debug");
+            static ConstString g_reloc_sect_name (".reloc");
+            static ConstString g_stab_sect_name (".stab");
+            static ConstString g_stabstr_sect_name (".stabstr");
+            SectionType section_type = eSectionTypeOther;
+            if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_CODE && 
+                ((const_sect_name == g_code_sect_name) || (const_sect_name == g_CODE_sect_name)))
+            {
+                section_type = eSectionTypeCode;
+            }
+            else if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_INITIALIZED_DATA && 
+                     ((const_sect_name == g_data_sect_name) || (const_sect_name == g_DATA_sect_name)))
+            {
+                section_type = eSectionTypeData;
+            }
+            else if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA && 
+                     ((const_sect_name == g_bss_sect_name) || (const_sect_name == g_BSS_sect_name)))
+            {
+                if (m_sect_headers[idx].size == 0)
+                    section_type = eSectionTypeZeroFill;
+                else
+                    section_type = eSectionTypeData;
+            }
+            else if (const_sect_name == g_debug_sect_name)
+            {
+                section_type = eSectionTypeDebug;
+            }
+            else if (const_sect_name == g_stabstr_sect_name)
+            {
+                section_type = eSectionTypeDataCString;
+            }
+            else if (const_sect_name == g_reloc_sect_name)
+            {
+                section_type = eSectionTypeOther;
+            }
+            else if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_CODE)
+            {
+                section_type = eSectionTypeCode;
+            }
+            else if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_INITIALIZED_DATA)
+            {
+                section_type = eSectionTypeData;
+            }
+            else if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+            {
+                if (m_sect_headers[idx].size == 0)
+                    section_type = eSectionTypeZeroFill;
+                else
+                    section_type = eSectionTypeData;
+            }
+
             // Use a segment ID of the segment index shifted left by 8 so they
             // never conflict with any of the sections.
             SectionSP section_sp (new Section (NULL,
                                                module,                       // Module to which this section belongs
                                                idx + 1,                      // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible
                                                const_sect_name,              // Name of this section
-                                               eSectionTypeCode,             // This section is a container of other sections.
+                                               section_type,                    // This section is a container of other sections.
                                                m_sect_headers[idx].vmaddr,   // File VM address == addresses as they are found in the object file
                                                m_sect_headers[idx].vmsize,   // VM size in bytes of this section
                                                m_sect_headers[idx].offset,   // Offset to the data for this section in the file
@@ -659,7 +775,7 @@
     s->Printf ("  reserved1               = 0x%8.8x\n", header.reserved1);
     s->Printf ("  image_size              = 0x%8.8x\n", header.image_size);
     s->Printf ("  header_size             = 0x%8.8x\n", header.header_size);
-    s->Printf ("  checksym                = 0x%8.8x\n", header.checksym);
+    s->Printf ("  checksum                = 0x%8.8x\n", header.checksum);
     s->Printf ("  subsystem               = 0x%4.4x\n", header.subsystem);
     s->Printf ("  dll_flags               = 0x%4.4x\n", header.dll_flags);
     s->Printf ("  stack_reserve_size      = 0x%16.16llx\n", header.stack_reserve_size);
@@ -671,7 +787,7 @@
     uint32_t i;
     for (i=0; i<header.data_dirs.size(); i++)
     {
-        s->Printf ("  data_dirs[%u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n", 
+        s->Printf ("  data_dirs[%2u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n", 
                    i,
                    header.data_dirs[i].vmaddr,
                    header.data_dirs[i].vmsize);
@@ -689,10 +805,10 @@
     GetSectionName(name, sh);
     s->Printf ("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x 0x%4.4x 0x%8.8x\n",
                name.c_str(),
-               sh.vmsize,
                sh.vmaddr,
-               sh.size,
+               sh.vmsize,
                sh.offset,
+               sh.size,
                sh.reloff,
                sh.lineoff,
                sh.nreloc,
@@ -711,15 +827,15 @@
 {
     
     s->PutCString ("Section Headers\n");
-    s->PutCString ("IDX  name             vm size  vm addr  size     offset   reloff   lineoff  nrel nlin flags\n");
-    s->PutCString ("==== ---------------- -------- -------- -------- -------- -------- -------- ---- ---- --------\n");
+    s->PutCString ("IDX  name             vm addr    vm size    file off   file size  reloc off  line off   nreloc nline  flags\n");
+    s->PutCString ("==== ---------------- ---------- ---------- ---------- ---------- ---------- ---------- ------ ------ ----------\n");
     
     uint32_t idx = 0;
     SectionHeaderCollIter pos, end = m_sect_headers.end();
     
     for (pos = m_sect_headers.begin(); pos != end; ++pos, ++idx)
     {
-        s->Printf ("[%2u]", idx);
+        s->Printf ("[%2u] ", idx);
         ObjectFilePECOFF::DumpSectionHeader(s, *pos);
     }
 }
diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
index b1e9e0e..5bfe2d6 100644
--- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -173,7 +173,7 @@
 		uint32_t	reserved1;
 		uint32_t	image_size;
 		uint32_t	header_size;
-		uint32_t	checksym;
+		uint32_t	checksum;
 		uint16_t	subsystem;
 		uint16_t	dll_flags;
 		uint64_t	stack_reserve_size;