[PATCH] D43819: [ELF] - Restrict section offsets that exceeds file size.

George Rimar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 27 06:03:32 PST 2018


grimar created this revision.
grimar added reviewers: ruiu, espindola, jhenderson.
Herald added subscribers: arichardson, emaste.

This is part of PR36515.

With some linkerscripts it is possible to get file offset overlaps
and overflows. Currently LLD checks overlaps in checkNoOverlappingSections().
And also we allow broken output with --no-inhibit-exec.
Problem is that sometimes final offset of sections is completely broken
and we calculate output file size wrong and might crash.

After investigation, I think best what we can do is to error out
when section offsets exceeding file size. That still allows moving location counter backwards
and parameters overlaping tested by checkNoOverlappingSections(),
but at the same time ensures that linker will never crash because of that.


https://reviews.llvm.org/D43819

Files:
  ELF/Writer.cpp
  test/ELF/linkerscript/sections-va-overflow.s


Index: test/ELF/linkerscript/sections-va-overflow.s
===================================================================
--- test/ELF/linkerscript/sections-va-overflow.s
+++ test/ELF/linkerscript/sections-va-overflow.s
@@ -0,0 +1,17 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "PHDRS{  ph_headers  PT_PHDR PHDRS;" > %t.script
+# RUN: echo "ph_text PT_LOAD FILEHDR PHDRS  FLAGS (0x1 | 0x4); }" >> %t.script
+# RUN: echo "SECTIONS { . = 0xffffffff20000000;" >> %t.script
+# RUN: echo "  .text : { *(.text*) } : ph_text .test 0x1000 : { BYTE(0) } }" >> %t.script
+# RUN: not ld.lld -o %t.so --script %t.script %t.o 2>&1 | FileCheck %s -check-prefix=ERR
+
+## Section .test has VA 0x1000 and placed in the same segment as section .text
+## with VA 0xffffffff20000000. That might be technically correct, but most probably
+## is a result of broken script file and causes file offset calculation overlow.
+## Seems we do not have to support it, so we don't and we report error in this case.
+# ERR: error: unable to place section .text at file offset [0xFFFFFFFF20000000 -> 0xFFFFFFFE40000000], check your linker script for overflows
+
+.global _start
+_start:
+  retq
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -1823,6 +1823,12 @@
   }
 }
 
+static std::string rangeToString(uint64_t Addr, uint64_t Len) {
+  if (Len == 0)
+    return "<emtpy range at 0x" + utohexstr(Addr) + ">";
+  return "[0x" + utohexstr(Addr) + " -> 0x" + utohexstr(Addr + Len - 1) + "]";
+}
+
 // Adjusts the file alignment for a given output section and returns
 // its new file offset. The file offset must be the same with its
 // virtual address (modulo the page size) so that the loader can load
@@ -1893,6 +1899,15 @@
 
   SectionHeaderOff = alignTo(Off, Config->Wordsize);
   FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
+
+  // It is possible to get file offset overlaps or overflows with linker
+  // script. We perform checks required in checkNoOverlappingSections() and want
+  // to fully restrict file size overflows here because it would crash linker.
+  for (OutputSection *Sec : OutputSections)
+    if (Sec->Offset >= FileSize)
+      error("unable to place section " + Sec->Name + " at file offset " +
+            rangeToString(Sec->Offset, Sec->Offset + Sec->Size) +
+            ", check your linker script for overflows");
 }
 
 // Finalize the program headers. We call this function after we assign
@@ -1931,13 +1946,6 @@
   }
 }
 
-static std::string rangeToString(uint64_t Addr, uint64_t Len) {
-  if (Len == 0)
-    return "<emtpy range at 0x" + utohexstr(Addr) + ">";
-  return "[0x" + utohexstr(Addr) + " -> 0x" +
-         utohexstr(Addr + Len - 1) + "]";
-}
-
 // Check whether sections overlap for a specific address range (file offsets,
 // load and virtual adresses).
 //


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D43819.136069.patch
Type: text/x-patch
Size: 2952 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180227/67b6ff08/attachment.bin>


More information about the llvm-commits mailing list