[Binary] Align the image offset in OffloadBinary
authorJoseph Huber <jhuber6@vols.utk.edu>
Sat, 4 Jun 2022 20:56:45 +0000 (16:56 -0400)
committerJoseph Huber <jhuber6@vols.utk.edu>
Tue, 7 Jun 2022 19:56:08 +0000 (15:56 -0400)
Summary:
The OffloadBinary wraps around an embedded device image, commonly an ELF
or LLVM BC file. These file formats have alignment requirements for
parsing, so if the image is stored at an un-aligned offset from the
beginning of the file we will be unable to parse the embeded image
without copying the image buffer. This patch adds alignment padding
before the binary image is appended to ensure we can parse the symbolic
file it contains in-place without copying memory.

llvm/lib/Object/OffloadBinary.cpp

index 498a991..fe5cc09 100644 (file)
@@ -48,14 +48,17 @@ OffloadBinary::write(const OffloadingImage &OffloadingData) {
   uint64_t StringEntrySize =
       sizeof(StringEntry) * OffloadingData.StringData.size();
 
+  // Make sure the image we're wrapping around is aligned as well.
+  uint64_t BinaryDataSize = alignTo(sizeof(Header) + sizeof(Entry) +
+                                        StringEntrySize + StrTab.getSize(),
+                                    getAlignment());
+
   // Create the header and fill in the offsets. The entry will be directly
   // placed after the header in memory. Align the size to the alignment of the
   // header so this can be placed contiguously in a single section.
   Header TheHeader;
-  TheHeader.Size =
-      alignTo(sizeof(Header) + sizeof(Entry) + StringEntrySize +
-                  OffloadingData.Image.getBufferSize() + StrTab.getSize(),
-              getAlignment());
+  TheHeader.Size = alignTo(
+      BinaryDataSize + OffloadingData.Image.getBufferSize(), getAlignment());
   TheHeader.EntryOffset = sizeof(Header);
   TheHeader.EntrySize = sizeof(Entry);
 
@@ -68,8 +71,7 @@ OffloadBinary::write(const OffloadingImage &OffloadingData) {
   TheEntry.StringOffset = sizeof(Header) + sizeof(Entry);
   TheEntry.NumStrings = OffloadingData.StringData.size();
 
-  TheEntry.ImageOffset =
-      sizeof(Header) + sizeof(Entry) + StringEntrySize + StrTab.getSize();
+  TheEntry.ImageOffset = BinaryDataSize;
   TheEntry.ImageSize = OffloadingData.Image.getBufferSize();
 
   SmallVector<char, 1024> Data;
@@ -83,6 +85,8 @@ OffloadBinary::write(const OffloadingImage &OffloadingData) {
     OS << StringRef(reinterpret_cast<char *>(&Map), sizeof(StringEntry));
   }
   StrTab.write(OS);
+  // Add padding to required image alignment.
+  OS.write_zeros(TheEntry.ImageOffset - OS.tell());
   OS << OffloadingData.Image.getBuffer();
 
   // Add final padding to required alignment.