[Lldb-commits] [lldb] r236818 - Fix parsing of the plt section for android-arm

Tamas Berghammer tberghammer at google.com
Fri May 8 02:40:06 PDT 2015


Author: tberghammer
Date: Fri May  8 04:40:05 2015
New Revision: 236818

URL: http://llvm.org/viewvc/llvm-project?rev=236818&view=rev
Log:
Fix parsing of the plt section for android-arm

The ELF data contains two different errors in some ELF files on android.
* The link field of the symbol table don't point to the plt section or
  to the dynsym section even when it is present in the ELF files.
* The size of the plt entries aren't specified in the section header of
  the plt section.

This CL adds some workarounds for these two issue with finding the
sections by name if the link field is empty and by using a heuristic to
calculate the size and offset of the plt entries.

Differential revision: http://reviews.llvm.org/D9560

Modified:
    lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=236818&r1=236817&r2=236818&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Fri May  8 04:40:05 2015
@@ -1537,6 +1537,17 @@ ObjectFileELF::GetSectionHeaderByIndex(l
     return NULL;
 }
 
+lldb::user_id_t
+ObjectFileELF::GetSectionIndexByName(const char* name)
+{
+    if (!name || !name[0] || !ParseSectionHeaders())
+        return 0;
+    for (size_t i = 1; i < m_section_headers.size(); ++i)
+        if (m_section_headers[i].section_name == ConstString(name))
+            return i;
+    return 0;
+}
+
 void
 ObjectFileELF::CreateSections(SectionList &unified_section_list)
 {
@@ -2108,6 +2119,36 @@ ObjectFileELF::PLTRelocationType()
     return 0;
 }
 
+// Returns the size of the normal plt entries and the offset of the first normal plt entry. The
+// 0th entry in the plt table is ususally a resolution entry which have different size in some
+// architectures then the rest of the plt entries.
+static std::pair<uint64_t, uint64_t>
+GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader* plt_hdr)
+{
+    const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
+
+    // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16 bytes.
+    // So round the entsize up by the alignment if addralign is set.
+    elf_xword plt_entsize = plt_hdr->sh_addralign ?
+        llvm::RoundUpToAlignment (plt_hdr->sh_entsize, plt_hdr->sh_addralign) : plt_hdr->sh_entsize;
+
+    if (plt_entsize == 0)
+    {
+        // The linker haven't set the plt_hdr->sh_entsize field. Try to guess the size of the plt
+        // entries based on the number of entries and the size of the plt section with the
+        // asumption that the size of the 0th entry is at least as big as the size of the normal
+        // entries and it isn't mutch bigger then that.
+        if (plt_hdr->sh_addralign)
+            plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign / (num_relocations + 1) * plt_hdr->sh_addralign;
+        else
+            plt_entsize = plt_hdr->sh_size / (num_relocations + 1);
+    }
+
+    elf_xword plt_offset = plt_hdr->sh_size - num_relocations * plt_entsize;
+
+    return std::make_pair(plt_entsize, plt_offset);
+}
+
 static unsigned
 ParsePLTRelocations(Symtab *symbol_table,
                     user_id_t start_id,
@@ -2124,10 +2165,9 @@ ParsePLTRelocations(Symtab *symbol_table
     ELFRelocation rel(rel_type);
     ELFSymbol symbol;
     lldb::offset_t offset = 0;
-    // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16 bytes.
-    // So round the entsize up by the alignment if addralign is set.
-    const elf_xword plt_entsize = plt_hdr->sh_addralign ?
-        llvm::RoundUpToAlignment (plt_hdr->sh_entsize, plt_hdr->sh_addralign) : plt_hdr->sh_entsize;
+
+    uint64_t plt_offset, plt_entsize;
+    std::tie(plt_entsize, plt_offset) = GetPltEntrySizeAndOffset(rel_hdr, plt_hdr);
     const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
 
     typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
@@ -2156,13 +2196,12 @@ ParsePLTRelocations(Symtab *symbol_table
             continue;
 
         lldb::offset_t symbol_offset = reloc_symbol(rel) * sym_hdr->sh_entsize;
-        uint64_t plt_index = (i + 1) * plt_entsize;
-
         if (!symbol.Parse(symtab_data, &symbol_offset))
             break;
 
         const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
         bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false;
+        uint64_t plt_index = plt_offset + i * plt_entsize;
 
         Symbol jump_symbol(
             i + start_id,    // Symbol table index
@@ -2199,6 +2238,13 @@ ObjectFileELF::ParseTrampolineSymbols(Sy
     user_id_t symtab_id = rel_hdr->sh_link;
     user_id_t plt_id = rel_hdr->sh_info;
 
+    // If the link field doesn't point to the appropriate symbol name table then
+    // try to find it by name as some compiler don't fill in the link fields.
+    if (!symtab_id)
+        symtab_id = GetSectionIndexByName(".dynsym");
+    if (!plt_id)
+        plt_id = GetSectionIndexByName(".plt");
+
     if (!symtab_id || !plt_id)
         return 0;
 





More information about the lldb-commits mailing list