[PATCH] D27526: [ELF] - Do not align file offset when -Ttext is specified.

George Rimar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 7 08:40:59 PST 2016


grimar created this revision.
grimar added reviewers: ruiu, rafael.
grimar added subscribers: llvm-commits, grimar, evgeny777, emaste.

-Ttext is a bit wierd feature and gold/bfd are inconsistent here.

I took loader reproduce from PR31295, which has:
--omagic -Ttext 0x0

LLD crashed before this patch, beacause tried to calculate offset with:

  return First->Offset + Sec->Addr - First->Addr;
  where First->Offset == 0x0, Sec->Addr == 0x0 (-Ttext), First->Addr = 0x10000 (Header)

gold linker ignores setting -Ttext to specified value. For example for case above it do:

  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000080 000080 00ba74 00  AX  0   0 16
  [ 2] .rodata           PROGBITS        0000bb00 00bb00 0035fc 00   A  0   0 16
  [ 3] .got              PROGBITS        0000f0fc 00f0fc 000000 00  WA  0   0  4

So noticable that address of .text is not what user specified. And file offsets are aligned.

bfd instead in the same situation looks ignores file offset aligning and do exactly what user asked:

  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000080 00ba74 00 WAX  0   0 16
  [ 2] .rodata           PROGBITS        0000ba80 00bb00 0035f4 00   A  0   0 16
  [ 3] .got.plt          PROGBITS        0000f074 00f0f4 00000c 04  WA  0   0  4

I think we can try to do the same for now, that what this patch do.
This fixes crash of PR31295.


https://reviews.llvm.org/D27526

Files:
  ELF/Writer.cpp
  test/ELF/ttext2.s


Index: test/ELF/ttext2.s
===================================================================
--- test/ELF/ttext2.s
+++ test/ELF/ttext2.s
@@ -0,0 +1,27 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+## Check that .text has VA 0x0. That matches bfd behavior.
+# RUN: ld.lld -N -Ttext 0x0 %t -o %t1
+# RUN: llvm-readobj -s %t1 | FileCheck %s
+# CHECK: Section {
+# CHECK:   Index: 1
+# CHECK:   Name: .text
+# CHECK-NEXT:   Type: SHT_PROGBITS
+# CHECK-NEXT:   Flags [
+# CHECK-NEXT:     SHF_ALLOC
+# CHECK-NEXT:     SHF_EXECINSTR
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Address: 0x0
+# CHECK-NEXT:   Offset: 0xE8
+# CHECK-NEXT:   Size:
+# CHECK-NEXT:   Link:
+# CHECK-NEXT:   Info:
+# CHECK-NEXT:   AddressAlignment:
+# CHECK-NEXT:   EntrySize:
+# CHECK-NEXT: }
+
+.text
+.globl _start
+_start:
+ nop
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -498,7 +498,18 @@
 template <class ELFT>
 static bool compareSectionsNonScript(const OutputSectionBase *A,
                                      const OutputSectionBase *B) {
-  // Put .interp first because some loaders want to see that section
+  // Some loaders use -Ttext option to set .text section address.
+  // In that case we place it at the begining to be able to
+  // assign VA in a simple forward loop later. That is consistent
+  // with what GNU gold do.
+  if (Config->SectionStartMap.count(".text")) {
+    bool AIsText = A->getName() == ".text";
+    bool BIsText = B->getName() == ".text";
+    if (AIsText != BIsText)
+      return AIsText;
+  }
+
+  // Put .interp early because some loaders want to see that section
   // on the first page of the executable file when loaded into memory.
   bool AIsInterp = A->getName() == ".interp";
   bool BIsInterp = B->getName() == ".interp";
@@ -1322,6 +1333,13 @@
   if (!First)
     return Off;
 
+  // Some loaders use -Ttext to set start address of text section.
+  // In that case behavior of GNU linkers inconsistent. bfd sets
+  // VA exactly to specified and stops aligning file offset.
+  // We match bfd here.
+  if (Config->SectionStartMap.count(".text"))
+    return Off;
+
   // If two sections share the same PT_LOAD the file offset is calculated using
   // this formula: Off2 = Off1 + (VA2 - VA1).
   if (Sec == First)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D27526.80601.patch
Type: text/x-patch
Size: 2365 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161207/cec42ff2/attachment.bin>


More information about the llvm-commits mailing list