Object, COFF: Cap the section contents to min(VirtualSize, SizeOfRawData)
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 9 Oct 2014 07:49:28 +0000 (07:49 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 9 Oct 2014 07:49:28 +0000 (07:49 +0000)
It is not useful to return the data beyond VirtualSize it's less than
SizeOfRawData.

An implementation detail of COFF requires the section size to be rounded
up to a multiple of FileAlignment; this means that SizeOfRawData is not
representative of how large the section is.  Instead, we should cap it
to VirtualSize when this occurs as it represents the true size of the
section.

Note that this is only relevant in executable files because this
rounding doesn't occur in object files (and VirtualSize is always zero).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219388 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Object/COFFObjectFile.cpp

index adc68ec62c5c4176069b8a41ca14d8f2fedb58d3..72a6db4aab9a57979e92cd994027d258319c1b04 100644 (file)
@@ -869,19 +869,33 @@ std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
 std::error_code
 COFFObjectFile::getSectionContents(const coff_section *Sec,
                                    ArrayRef<uint8_t> &Res) const {
-  // PointerToRawData and SizeOfRawData won't make sense for BSS sections, don't
-  // do anything interesting for them.
+  // PointerToRawData and SizeOfRawData won't make sense for BSS sections,
+  // don't do anything interesting for them.
   assert((Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 &&
          "BSS sections don't have contents!");
   // The only thing that we need to verify is that the contents is contained
   // within the file bounds. We don't need to make sure it doesn't cover other
   // data, as there's nothing that says that is not allowed.
   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
-  uintptr_t ConEnd = ConStart + Sec->SizeOfRawData;
+  // SizeOfRawData and VirtualSize change what they represent depending on
+  // whether or not we have an executable image.
+  //
+  // For object files, SizeOfRawData contains the size of section's data;
+  // VirtualSize is always zero.
+  //
+  // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
+  // actual section size is in VirtualSize.  It is possible for VirtualSize to
+  // be greater than SizeOfRawData; the contents past that point should be
+  // considered to be zero.
+  uint32_t DataSize;
+  if (Sec->VirtualSize)
+    DataSize = std::min(Sec->VirtualSize, Sec->SizeOfRawData);
+  else
+    DataSize = Sec->SizeOfRawData;
+  uintptr_t ConEnd = ConStart + DataSize;
   if (ConEnd > uintptr_t(Data.getBufferEnd()))
     return object_error::parse_failed;
-  Res = makeArrayRef(reinterpret_cast<const uint8_t*>(ConStart),
-                     Sec->SizeOfRawData);
+  Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), DataSize);
   return object_error::success;
 }