[Lldb-commits] [lldb] r147358 - in /lldb/trunk: include/lldb/Core/DataExtractor.h source/Core/DataExtractor.cpp source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Greg Clayton gclayton at apple.com
Thu Dec 29 16:32:24 PST 2011


Author: gclayton
Date: Thu Dec 29 18:32:24 2011
New Revision: 147358

URL: http://llvm.org/viewvc/llvm-project?rev=147358&view=rev
Log:
<rdar://problem/10368163>

Watch for empty symbol tables by doing a lot more error checking on
all mach-o symbol table load command values and data that is obtained.
This avoids a crash that was happening when there was no string table.


Modified:
    lldb/trunk/include/lldb/Core/DataExtractor.h
    lldb/trunk/source/Core/DataExtractor.cpp
    lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Modified: lldb/trunk/include/lldb/Core/DataExtractor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/DataExtractor.h?rev=147358&r1=147357&r2=147358&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/DataExtractor.h (original)
+++ lldb/trunk/include/lldb/Core/DataExtractor.h Thu Dec 29 18:32:24 2011
@@ -354,6 +354,9 @@
     //------------------------------------------------------------------
     uint64_t
     GetAddress (uint32_t *offset_ptr) const;
+    
+    uint64_t
+    GetAddress_unchecked (uint32_t *offset_ptr) const;
 
     //------------------------------------------------------------------
     /// Get the current address size.
@@ -629,6 +632,9 @@
     uint64_t
     GetMaxU64 (uint32_t *offset_ptr, uint32_t byte_size) const;
 
+    uint64_t
+    GetMaxU64_unchecked (uint32_t *offset_ptr, uint32_t byte_size) const;
+
     //------------------------------------------------------------------
     /// Extract an signed integer of size \a byte_size from \a *offset_ptr.
     ///

Modified: lldb/trunk/source/Core/DataExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DataExtractor.cpp?rev=147358&r1=147357&r2=147358&view=diff
==============================================================================
--- lldb/trunk/source/Core/DataExtractor.cpp (original)
+++ lldb/trunk/source/Core/DataExtractor.cpp Thu Dec 29 18:32:24 2011
@@ -659,6 +659,22 @@
     return 0;
 }
 
+uint64_t
+DataExtractor::GetMaxU64_unchecked (uint32_t *offset_ptr, uint32_t size) const
+{
+    switch (size)
+    {
+        case 1: return GetU8_unchecked  (offset_ptr); break;
+        case 2: return GetU16_unchecked (offset_ptr); break;
+        case 4: return GetU32_unchecked (offset_ptr); break;
+        case 8: return GetU64_unchecked (offset_ptr); break;
+        default:
+            assert(!"GetMax64 unhandled case!");
+            break;
+    }
+    return 0;
+}
+
 int64_t
 DataExtractor::GetMaxS64 (uint32_t *offset_ptr, uint32_t size) const
 {
@@ -803,6 +819,12 @@
     return GetMaxU64 (offset_ptr, m_addr_size);
 }
 
+uint64_t
+DataExtractor::GetAddress_unchecked (uint32_t *offset_ptr) const
+{
+    return GetMaxU64_unchecked (offset_ptr, m_addr_size);
+}
+
 //------------------------------------------------------------------
 // Extract a single pointer from the data and update the offset
 // pointed to by "offset_ptr". The size of the extracted pointer

Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=147358&r1=147357&r2=147358&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Thu Dec 29 18:32:24 2011
@@ -752,6 +752,9 @@
     struct symtab_command symtab_load_command;
     uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
     uint32_t i;
+    
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
+
     for (i=0; i<m_header.ncmds; ++i)
     {
         const uint32_t cmd_offset = offset;
@@ -764,16 +767,67 @@
             // Read in the rest of the symtab load command
             if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4)) // fill in symoff, nsyms, stroff, strsize fields
             {
+                if (symtab_load_command.symoff == 0)
+                {
+                    if (log)
+                        GetModule()->LogMessage(log.get(), "LC_SYMTAB.symoff == 0");
+                    return 0;
+                }
+
+                if (symtab_load_command.stroff == 0)
+                {
+                    if (log)
+                        GetModule()->LogMessage(log.get(), "LC_SYMTAB.stroff == 0");
+                    return 0;
+                }
+                
+                if (symtab_load_command.nsyms == 0)
+                {
+                    if (log)
+                        GetModule()->LogMessage(log.get(), "LC_SYMTAB.nsyms == 0");
+                    return 0;
+                }
+                
+                if (symtab_load_command.strsize == 0)
+                {
+                    if (log)
+                        GetModule()->LogMessage(log.get(), "LC_SYMTAB.strsize == 0");
+                    return 0;
+                }
+
                 Symtab *symtab = m_symtab_ap.get();
                 SectionList *section_list = GetSectionList();
-                assert(section_list);
-                const size_t addr_size = m_data.GetAddressByteSize();
-                const ByteOrder endian = m_data.GetByteOrder();
-                bool bit_width_32 = addr_size == 4;
-                const size_t nlist_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64);
+                if (section_list == NULL)
+                    return 0;
+
+                const size_t addr_byte_size = m_data.GetAddressByteSize();
+                const ByteOrder byte_order = m_data.GetByteOrder();
+                bool bit_width_32 = addr_byte_size == 4;
+                const size_t nlist_byte_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64);
+
+                DataBufferSP symtab_data_sp(m_file.ReadFileContents (m_offset + symtab_load_command.symoff, 
+                                                                     symtab_load_command.nsyms * nlist_byte_size));
+
+                if (symtab_data_sp.get() == NULL || 
+                    symtab_data_sp->GetBytes() == NULL ||
+                    symtab_data_sp->GetByteSize() == 0)
+                {
+                    if (log)
+                        GetModule()->LogMessage(log.get(), "failed to read nlist data");
+                    return 0;
+                }
+
+                DataBufferSP strtab_data_sp(m_file.ReadFileContents (m_offset + symtab_load_command.stroff, 
+                                                                     symtab_load_command.strsize));
 
-                DataBufferSP symtab_data_sp(m_file.ReadFileContents(m_offset + symtab_load_command.symoff, symtab_load_command.nsyms * nlist_size));
-                DataBufferSP strtab_data_sp(m_file.ReadFileContents(m_offset + symtab_load_command.stroff, symtab_load_command.strsize));
+                if (strtab_data_sp.get() == NULL || 
+                    strtab_data_sp->GetBytes() == NULL ||
+                    strtab_data_sp->GetByteSize() == 0)
+                {
+                    if (log)
+                        GetModule()->LogMessage(log.get(), "failed to read strtab data");
+                    return 0;
+                }
 
                 const char *strtab_data = (const char *)strtab_data_sp->GetBytes();
                 const size_t strtab_data_len = strtab_data_sp->GetByteSize();
@@ -793,15 +847,11 @@
 
                 uint8_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NListSectionNoSection;
                 //uint32_t symtab_offset = 0;
-                const uint8_t* nlist_data = symtab_data_sp->GetBytes();
-                assert (symtab_data_sp->GetByteSize()/nlist_size >= symtab_load_command.nsyms);
+                assert (symtab_data_sp->GetByteSize()/nlist_byte_size >= symtab_load_command.nsyms);
 
+                uint32_t nlist_data_offset = 0;
+                DataExtractor nlist_data (symtab_data_sp, byte_order, addr_byte_size);
 
-                if (endian != lldb::endian::InlHostByteOrder())
-                {
-                    // ...
-                    assert (!"UNIMPLEMENTED: Swap all nlist entries");
-                }
                 uint32_t N_SO_index = UINT32_MAX;
 
                 MachSymtabSectionInfo section_info (section_list);
@@ -828,19 +878,14 @@
                 for (nlist_idx = 0; nlist_idx < symtab_load_command.nsyms; ++nlist_idx)
                 {
                     struct nlist_64 nlist;
-                    if (bit_width_32)
-                    {
-                        struct nlist* nlist32_ptr = (struct nlist*)(nlist_data + (nlist_idx * nlist_size));
-                        nlist.n_strx = nlist32_ptr->n_strx;
-                        nlist.n_type = nlist32_ptr->n_type;
-                        nlist.n_sect = nlist32_ptr->n_sect;
-                        nlist.n_desc = nlist32_ptr->n_desc;
-                        nlist.n_value = nlist32_ptr->n_value;
-                    }
-                    else
-                    {
-                        nlist = *((struct nlist_64*)(nlist_data + (nlist_idx * nlist_size)));
-                    }
+                    if (!nlist_data.ValidOffsetForDataOfSize(nlist_data_offset, nlist_byte_size))
+                        break;
+
+                    nlist.n_strx  = nlist_data.GetU32_unchecked(&nlist_data_offset);
+                    nlist.n_type  = nlist_data.GetU8_unchecked (&nlist_data_offset);
+                    nlist.n_sect  = nlist_data.GetU8_unchecked (&nlist_data_offset);
+                    nlist.n_desc  = nlist_data.GetU16_unchecked (&nlist_data_offset);
+                    nlist.n_value = nlist_data.GetAddress_unchecked (&nlist_data_offset);
 
                     SymbolType type = eSymbolTypeInvalid;
                     if (nlist.n_strx >= strtab_data_len)
@@ -1556,9 +1601,6 @@
                         }
                     }
                 }
-                
-                
-
                 return symtab->GetNumSymbols();
             }
         }





More information about the lldb-commits mailing list