[llvm-commits] [llvm] r123962 - in /llvm/trunk: include/llvm/Object/ObjectFile.h lib/Object/COFFObjectFile.cpp lib/Object/ELFObjectFile.cpp

Michael J. Spencer bigcheesegs at gmail.com
Thu Jan 20 18:27:02 PST 2011


Author: mspencer
Date: Thu Jan 20 20:27:02 2011
New Revision: 123962

URL: http://llvm.org/viewvc/llvm-project?rev=123962&view=rev
Log:
Object: Fix type punned pointer issues by making DataRefImpl a union and using intptr_t.

Modified:
    llvm/trunk/include/llvm/Object/ObjectFile.h
    llvm/trunk/lib/Object/COFFObjectFile.cpp
    llvm/trunk/lib/Object/ELFObjectFile.cpp

Modified: llvm/trunk/include/llvm/Object/ObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ObjectFile.h?rev=123962&r1=123961&r2=123962&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/ObjectFile.h Thu Jan 20 20:27:02 2011
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/DataTypes.h"
+#include <cstring>
 
 namespace llvm {
 
@@ -25,7 +26,19 @@
 namespace object {
 
 class ObjectFile;
-typedef uint64_t DataRefImpl;
+
+union DataRefImpl {
+  struct {
+    uint32_t a, b;
+  } d;
+  intptr_t p;
+};
+
+static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) {
+  // Check bitwise identical. This is the only legal way to compare a union w/o
+  // knowing which member is in use.
+  return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0;
+}
 
 /// SymbolRef - This is a value type class that represents a single symbol in
 /// the list of symbols in the object file.

Modified: llvm/trunk/lib/Object/COFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/COFFObjectFile.cpp?rev=123962&r1=123961&r2=123962&view=diff
==============================================================================
--- llvm/trunk/lib/Object/COFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/COFFObjectFile.cpp Thu Jan 20 20:27:02 2011
@@ -128,13 +128,14 @@
 } // end namespace
 
 SymbolRef COFFObjectFile::getSymbolNext(DataRefImpl Symb) const {
-  const coff_symbol *symb = *reinterpret_cast<const coff_symbol**>(&Symb);
+  const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p);
   symb += 1 + symb->NumberOfAuxSymbols;
-  return SymbolRef(DataRefImpl(symb), this);
+  Symb.p = reinterpret_cast<intptr_t>(symb);
+  return SymbolRef(Symb, this);
 }
 
 StringRef COFFObjectFile::getSymbolName(DataRefImpl Symb) const {
-  const coff_symbol *symb = *reinterpret_cast<const coff_symbol**>(&Symb);
+  const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p);
   // Check for string table entry. First 4 bytes are 0.
   if (symb->Name.Offset.Zeroes == 0) {
     uint32_t Offset = symb->Name.Offset.Offset;
@@ -149,7 +150,7 @@
 }
 
 uint64_t COFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
-  const coff_symbol *symb = *reinterpret_cast<const coff_symbol**>(&Symb);
+  const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p);
   const coff_section *Section = getSection(symb->SectionNumber);
   char Type = getSymbolNMTypeChar(Symb);
   if (Type == 'U' || Type == 'w')
@@ -163,7 +164,7 @@
   // FIXME: Return the correct size. This requires looking at all the symbols
   //        in the same section as this symbol, and looking for either the next
   //        symbol, or the end of the section.
-  const coff_symbol *symb = *reinterpret_cast<const coff_symbol**>(&Symb);
+  const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p);
   const coff_section *Section = getSection(symb->SectionNumber);
   char Type = getSymbolNMTypeChar(Symb);
   if (Type == 'U' || Type == 'w')
@@ -174,7 +175,7 @@
 }
 
 char COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb) const {
-  const coff_symbol *symb = *reinterpret_cast<const coff_symbol**>(&Symb);
+  const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p);
   char ret = StringSwitch<char>(getSymbolName(Symb))
     .StartsWith(".debug", 'N')
     .StartsWith(".sxdata", 'N')
@@ -236,13 +237,14 @@
 }
 
 SectionRef COFFObjectFile::getSectionNext(DataRefImpl Sec) const {
-  const coff_section *sec = *reinterpret_cast<const coff_section**>(&Sec);
+  const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p);
   sec += 1;
-  return SectionRef(DataRefImpl(sec), this);
+  Sec.p = reinterpret_cast<intptr_t>(sec);
+  return SectionRef(Sec, this);
 }
 
 StringRef COFFObjectFile::getSectionName(DataRefImpl Sec) const {
-  const coff_section *sec = *reinterpret_cast<const coff_section**>(&Sec);
+  const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p);
   StringRef name;
   if (sec->Name[7] == 0)
     // Null terminated, let ::strlen figure out the length.
@@ -263,23 +265,23 @@
 }
 
 uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
-  const coff_section *sec = *reinterpret_cast<const coff_section**>(&Sec);
+  const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p);
   return sec->VirtualAddress;
 }
 
 uint64_t COFFObjectFile::getSectionSize(DataRefImpl Sec) const {
-  const coff_section *sec = *reinterpret_cast<const coff_section**>(&Sec);
+  const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p);
   return sec->SizeOfRawData;
 }
 
 StringRef COFFObjectFile::getSectionContents(DataRefImpl Sec) const {
-  const coff_section *sec = *reinterpret_cast<const coff_section**>(&Sec);
+  const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p);
   return StringRef(reinterpret_cast<const char *>(base + sec->PointerToRawData),
                    sec->SizeOfRawData);
 }
 
 bool COFFObjectFile::isSectionText(DataRefImpl Sec) const {
-  const coff_section *sec = *reinterpret_cast<const coff_section**>(&Sec);
+  const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p);
   return sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
 }
 
@@ -300,29 +302,32 @@
 }
 
 ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const {
-  return symbol_iterator(
-    SymbolRef(DataRefImpl(SymbolTable), this));
+  DataRefImpl ret;
+  ret.p = reinterpret_cast<intptr_t>(SymbolTable);
+  return symbol_iterator(SymbolRef(ret, this));
 }
 
 ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const {
   // The symbol table ends where the string table begins.
-  return symbol_iterator(
-    SymbolRef(DataRefImpl(StringTable), this));
+  DataRefImpl ret;
+  ret.p = reinterpret_cast<intptr_t>(StringTable);
+  return symbol_iterator(SymbolRef(ret, this));
 }
 
 ObjectFile::section_iterator COFFObjectFile::begin_sections() const {
-  return section_iterator(
-    SectionRef(DataRefImpl(SectionTable), this));
+  DataRefImpl ret;
+  ret.p = reinterpret_cast<intptr_t>(SectionTable);
+  return section_iterator(SectionRef(ret, this));
 }
 
 ObjectFile::section_iterator COFFObjectFile::end_sections() const {
-  return section_iterator(
-    SectionRef(
-      DataRefImpl((void *)(SectionTable + Header->NumberOfSections)), this));
+  DataRefImpl ret;
+  ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections);
+  return section_iterator(SectionRef(ret, this));
 }
 
 uint8_t COFFObjectFile::getBytesInAddress() const {
-  return 4;
+  return getArch() == Triple::x86_64 ? 8 : 4;
 }
 
 StringRef COFFObjectFile::getFileFormatName() const {

Modified: llvm/trunk/lib/Object/ELFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ELFObjectFile.cpp?rev=123962&r1=123961&r2=123962&view=diff
==============================================================================
--- llvm/trunk/lib/Object/ELFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/ELFObjectFile.cpp Thu Jan 20 20:27:02 2011
@@ -128,8 +128,7 @@
   unsigned getEntityCount() const {
     if (sh_entsize == 0)
       return 0;
-    else
-      return sh_size / sh_entsize;
+    return sh_size / sh_entsize;
   }
 };
 }
@@ -177,14 +176,6 @@
 }
 
 namespace {
-struct ELFDataRefImpl {
-  uint32_t SymbolIndex;
-  uint16_t SymbolTableSectionIndex;
-  uint16_t Unused;
-};
-}
-
-namespace {
 template<support::endianness target_endianness, bool is64Bits>
 class ELFObjectFile : public ObjectFile {
   LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
@@ -261,10 +252,8 @@
 template<support::endianness target_endianness, bool is64Bits>
 void ELFObjectFile<target_endianness, is64Bits>
                   ::validateSymbol(DataRefImpl Symb) const {
-  const ELFDataRefImpl SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb);
   const Elf_Sym  *symb = getSymbol(Symb);
-  const Elf_Shdr *SymbolTableSection =
-    SymbolTableSections[SymbolData.SymbolTableSectionIndex];
+  const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b];
   // FIXME: We really need to do proper error handling in the case of an invalid
   //        input file. Because we don't use exceptions, I think we'll just pass
   //        an error object around.
@@ -283,20 +272,18 @@
 SymbolRef ELFObjectFile<target_endianness, is64Bits>
                        ::getSymbolNext(DataRefImpl Symb) const {
   validateSymbol(Symb);
-  ELFDataRefImpl &SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb);
-  const Elf_Shdr *SymbolTableSection =
-    SymbolTableSections[SymbolData.SymbolTableSectionIndex];
+  const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b];
 
-  ++SymbolData.SymbolIndex;
+  ++Symb.d.a;
   // Check to see if we are at the end of this symbol table.
-  if (SymbolData.SymbolIndex >= SymbolTableSection->getEntityCount()) {
+  if (Symb.d.a >= SymbolTableSection->getEntityCount()) {
     // We are at the end. If there are other symbol tables, jump to them.
-    ++SymbolData.SymbolTableSectionIndex;
-    SymbolData.SymbolIndex = 1; // The 0th symbol in ELF is fake.
+    ++Symb.d.b;
+    Symb.d.a = 1; // The 0th symbol in ELF is fake.
     // Otherwise return the terminator.
-    if (SymbolData.SymbolTableSectionIndex >= SymbolTableSections.size()) {
-      SymbolData.SymbolIndex = std::numeric_limits<uint32_t>::max();
-      SymbolData.SymbolTableSectionIndex = std::numeric_limits<uint32_t>::max();
+    if (Symb.d.b >= SymbolTableSections.size()) {
+      Symb.d.a = std::numeric_limits<uint32_t>::max();
+      Symb.d.b = std::numeric_limits<uint32_t>::max();
     }
   }
 
@@ -426,40 +413,37 @@
 template<support::endianness target_endianness, bool is64Bits>
 SectionRef ELFObjectFile<target_endianness, is64Bits>
                         ::getSectionNext(DataRefImpl Sec) const {
-  const uint8_t *sec = *reinterpret_cast<const uint8_t **>(&Sec);
+  const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p);
   sec += Header->e_shentsize;
-  return SectionRef(DataRefImpl(sec), this);
+  Sec.p = reinterpret_cast<intptr_t>(sec);
+  return SectionRef(Sec, this);
 }
 
 template<support::endianness target_endianness, bool is64Bits>
 StringRef ELFObjectFile<target_endianness, is64Bits>
                        ::getSectionName(DataRefImpl Sec) const {
-  const Elf_Shdr *sec =
-    *reinterpret_cast<const Elf_Shdr **>(&Sec);
+  const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
   return StringRef(getString(dot_shstrtab_sec, sec->sh_name));
 }
 
 template<support::endianness target_endianness, bool is64Bits>
 uint64_t ELFObjectFile<target_endianness, is64Bits>
                       ::getSectionAddress(DataRefImpl Sec) const {
-  const Elf_Shdr *sec =
-    *reinterpret_cast<const Elf_Shdr **>(&Sec);
+  const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
   return sec->sh_addr;
 }
 
 template<support::endianness target_endianness, bool is64Bits>
 uint64_t ELFObjectFile<target_endianness, is64Bits>
                       ::getSectionSize(DataRefImpl Sec) const {
-  const Elf_Shdr *sec =
-    *reinterpret_cast<const Elf_Shdr **>(&Sec);
+  const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
   return sec->sh_size;
 }
 
 template<support::endianness target_endianness, bool is64Bits>
 StringRef ELFObjectFile<target_endianness, is64Bits>
                        ::getSectionContents(DataRefImpl Sec) const {
-  const Elf_Shdr *sec =
-    *reinterpret_cast<const Elf_Shdr **>(&Sec);
+  const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
   const char *start = (char*)base + sec->sh_offset;
   return StringRef(start, sec->sh_size);
 }
@@ -467,8 +451,7 @@
 template<support::endianness target_endianness, bool is64Bits>
 bool ELFObjectFile<target_endianness, is64Bits>
                   ::isSectionText(DataRefImpl Sec) const {
-  const Elf_Shdr *sec =
-    *reinterpret_cast<const Elf_Shdr **>(&Sec);
+  const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
   if (sec->sh_flags & ELF::SHF_EXECINSTR)
     return true;
   return false;
@@ -538,49 +521,49 @@
 template<support::endianness target_endianness, bool is64Bits>
 ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits>
                                          ::begin_symbols() const {
-  ELFDataRefImpl SymbolData;
+  DataRefImpl SymbolData;
   memset(&SymbolData, 0, sizeof(SymbolData));
   if (SymbolTableSections.size() == 0) {
-    SymbolData.SymbolIndex = std::numeric_limits<uint32_t>::max();
-    SymbolData.SymbolTableSectionIndex = std::numeric_limits<uint32_t>::max();
+    SymbolData.d.a = std::numeric_limits<uint32_t>::max();
+    SymbolData.d.b = std::numeric_limits<uint32_t>::max();
   } else {
-    SymbolData.SymbolIndex = 1; // The 0th symbol in ELF is fake.
-    SymbolData.SymbolTableSectionIndex = 0;
+    SymbolData.d.a = 1; // The 0th symbol in ELF is fake.
+    SymbolData.d.b = 0;
   }
-  return symbol_iterator(
-    SymbolRef(DataRefImpl(*reinterpret_cast<DataRefImpl*>(&SymbolData)), this));
+  return symbol_iterator(SymbolRef(SymbolData, this));
 }
 
 template<support::endianness target_endianness, bool is64Bits>
 ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits>
                                          ::end_symbols() const {
-  ELFDataRefImpl SymbolData;
+  DataRefImpl SymbolData;
   memset(&SymbolData, 0, sizeof(SymbolData));
-  SymbolData.SymbolIndex = std::numeric_limits<uint32_t>::max();
-  SymbolData.SymbolTableSectionIndex = std::numeric_limits<uint32_t>::max();
-  return symbol_iterator(
-    SymbolRef(DataRefImpl(*reinterpret_cast<DataRefImpl*>(&SymbolData)), this));
+  SymbolData.d.a = std::numeric_limits<uint32_t>::max();
+  SymbolData.d.b = std::numeric_limits<uint32_t>::max();
+  return symbol_iterator(SymbolRef(SymbolData, this));
 }
 
 template<support::endianness target_endianness, bool is64Bits>
 ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
                                           ::begin_sections() const {
-  return section_iterator(
-    SectionRef(DataRefImpl(base + Header->e_shoff), this));
+  DataRefImpl ret;
+  ret.p = reinterpret_cast<intptr_t>(base + Header->e_shoff);
+  return section_iterator(SectionRef(ret, this));
 }
 
 template<support::endianness target_endianness, bool is64Bits>
 ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
                                           ::end_sections() const {
-  return section_iterator(
-    SectionRef(DataRefImpl(base
-                           + Header->e_shoff
-                           + (Header->e_shentsize * Header->e_shnum)), this));
+  DataRefImpl ret;
+  ret.p = reinterpret_cast<intptr_t>(base
+                                     + Header->e_shoff
+                                     + (Header->e_shentsize * Header->e_shnum));
+  return section_iterator(SectionRef(ret, this));
 }
 
 template<support::endianness target_endianness, bool is64Bits>
 uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const {
-  return 4;
+  return is64Bits ? 8 : 4;
 }
 
 template<support::endianness target_endianness, bool is64Bits>
@@ -626,20 +609,17 @@
 template<support::endianness target_endianness, bool is64Bits>
 const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym *
 ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const {
-  const ELFDataRefImpl SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb);
-  const Elf_Shdr *sec =
-    SymbolTableSections[SymbolData.SymbolTableSectionIndex];
+  const Elf_Shdr *sec = SymbolTableSections[Symb.d.b];
   return reinterpret_cast<const Elf_Sym *>(
            base
            + sec->sh_offset
-           + (SymbolData.SymbolIndex * sec->sh_entsize));
+           + (Symb.d.a * sec->sh_entsize));
 }
 
 template<support::endianness target_endianness, bool is64Bits>
 const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
 ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const {
-  const ELFDataRefImpl SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb);
-  const Elf_Shdr *sec = getSection(SymbolData.SymbolTableSectionIndex);
+  const Elf_Shdr *sec = getSection(Symb.d.b);
   if (sec->sh_type != ELF::SHT_SYMTAB)
     // FIXME: Proper error handling.
     report_fatal_error("Invalid symbol table section!");





More information about the llvm-commits mailing list