[PATCH] D37998: Tweak orphan section placement
Rafael Ávila de Espíndola via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 18 14:15:36 PDT 2017
rafael created this revision.
Herald added a subscriber: emaste.
Filipe noticed that given a linker script that ended in
.some_sec { ...} ;
__stack_start = .;
. = . + 0x2000;
__stack_end = .;
lld would put orphan sections like .comment before __stack_end, corrupting the intended meaning.
The reason we don't normally move orphans past assignments to . is to avoid breaking
rx_sec : { *(rx_sec) }
. = ALIGN(0x1000);
/* The RW PT_LOAD starts here*/
but in this case, there is nothing after and it seems safer to put the orphan section last. This seems to match bfd's behavior and is convenient for writing linker scripts that care about the layout of SHF_ALLOC sections, but not of any non SHF_ALLOC sections.
https://reviews.llvm.org/D37998
Files:
ELF/Writer.cpp
test/ELF/linkerscript/orphan-end.s
Index: test/ELF/linkerscript/orphan-end.s
===================================================================
--- /dev/null
+++ test/ELF/linkerscript/orphan-end.s
@@ -0,0 +1,57 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+
+# Test that .orphan_rx is placed after __stack_end. This matches bfd's
+# behavior when the orphan section is the last one.
+
+# RUN: echo "SECTIONS { \
+# RUN: __start_text = .; \
+# RUN: .text : { *(.text*) } \
+# RUN: __end_text = .; \
+# RUN: __stack_start = .; \
+# RUN: . = . + 0x1000; \
+# RUN: __stack_end = .; \
+# RUN: }" > %t.script
+# RUN: ld.lld -o %t --script %t.script %t.o
+# RUN: llvm-readelf -S --symbols %t | FileCheck %s
+
+# CHECK-DAG: .text PROGBITS 0000000000000000
+# CHECK-DAG: .orphan_rx PROGBITS 0000000000001004
+
+# CHECK-DAG: 0000000000000000 {{.*}} __start_text
+# CHECK-DAG: 0000000000000004 {{.*}} __end_text
+# CHECK-DAG: 0000000000000004 {{.*}} __stack_start
+# CHECK-DAG: 0000000000001004 {{.*}} __stack_end
+
+# Test that .orphan_rx is now placed before __stack_end. This matches bfd's
+# behavior when the orphan section is not the last one.
+
+# RUN: echo "SECTIONS { \
+# RUN: __start_text = .; \
+# RUN: .text : { *(.text*) } \
+# RUN: __end_text = .; \
+# RUN: __stack_start = .; \
+# RUN: . = . + 0x1000; \
+# RUN: __stack_end = .; \
+# RUN: .orphan_rw : { *(.orphan_rw*) } \
+# RUN: }" > %t.script
+# RUN: ld.lld -o %t --script %t.script %t.o
+# RUN: llvm-readelf -S --symbols %t | FileCheck --check-prefix=MIDDLE %s
+
+# MIDDLE-DAG: .text PROGBITS 0000000000000000
+# MIDDLE-DAG: .orphan_rx PROGBITS 0000000000000004
+
+# MIDDLE-DAG: 0000000000000000 {{.*}} __start_text
+# MIDDLE-DAG: 0000000000000004 {{.*}} __end_text
+# MIDDLE-DAG: 0000000000000004 {{.*}} __stack_start
+# MIDDLE-DAG: 0000000000001008 {{.*}} __stack_end
+
+ .global _start
+_start:
+ .zero 4
+
+ .section .orphan_rx,"ax"
+ .zero 4
+
+ .section .orphan_rw,"aw"
+ .zero 4
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -1043,6 +1043,17 @@
llvm::make_reverse_iterator(I), llvm::make_reverse_iterator(B),
[](BaseCommand *Cmd) { return isa<OutputSection>(Cmd); });
I = J.base();
+
+ // As a special case, if the orphan section is the last section, put
+ // it at the very end, past any other commands.
+ // This matches bfd's behavior and is convenient when the linker script fully
+ // specifies the start of the file, but doesn't care about the end (the non
+ // alloc sections for example).
+ auto NextSec = std::find_if(
+ I, E, [](BaseCommand *Cmd) { return isa<OutputSection>(Cmd); });
+ if (NextSec == E)
+ return E;
+
while (I != E && shouldSkip(*I))
++I;
return I;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D37998.115715.patch
Type: text/x-patch
Size: 3058 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170918/9b54106e/attachment.bin>
More information about the llvm-commits
mailing list