summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Ng <anng.sw@gmail.com>2018-07-23 11:29:46 +0000
committerAndrew Ng <anng.sw@gmail.com>2018-07-23 11:29:46 +0000
commite33d69199027e68916208bcea4924193b7f88d63 (patch)
treea2b5a45dd0bf06412a19c79427a75f0e708e46c1
parentfae3f89088b870dec1c39c83634cc27a44822f9a (diff)
downloadbcm5719-llvm-e33d69199027e68916208bcea4924193b7f88d63.tar.gz
bcm5719-llvm-e33d69199027e68916208bcea4924193b7f88d63.zip
[ELF] Fix handling of FDE negative relative PC addr
Signed values for the FDE PC addr were not correctly handled in readFdeAddr(). If the value is negative and the type of the value is smaller than 64 bits, the FDE PC addr overflow error would be incorrectly triggered. Fixed readFdeAddr() to properly handle signed values by sign extending where appropriate. Differential Revision: https://reviews.llvm.org/D49557 llvm-svn: 337683
-rw-r--r--lld/ELF/SyntheticSections.cpp7
-rw-r--r--lld/test/ELF/eh-frame-negative-pcrel-sdata2.s85
-rw-r--r--lld/test/ELF/eh-frame-negative-pcrel-sdata4.s85
-rw-r--r--lld/test/ELF/eh-frame-negative-pcrel-sdata8.s85
4 files changed, 261 insertions, 1 deletions
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 4bf6de5ba64..cbcf6bf39a1 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -534,9 +534,14 @@ static uint64_t readFdeAddr(uint8_t *Buf, int Size) {
switch (Size) {
case DW_EH_PE_udata2:
return read16(Buf);
+ case DW_EH_PE_sdata2:
+ return (int16_t)read16(Buf);
case DW_EH_PE_udata4:
return read32(Buf);
+ case DW_EH_PE_sdata4:
+ return (int32_t)read32(Buf);
case DW_EH_PE_udata8:
+ case DW_EH_PE_sdata8:
return read64(Buf);
case DW_EH_PE_absptr:
return readUint(Buf);
@@ -551,7 +556,7 @@ uint64_t EhFrameSection::getFdePc(uint8_t *Buf, size_t FdeOff,
// The starting address to which this FDE applies is
// stored at FDE + 8 byte.
size_t Off = FdeOff + 8;
- uint64_t Addr = readFdeAddr(Buf + Off, Enc & 0x7);
+ uint64_t Addr = readFdeAddr(Buf + Off, Enc & 0xf);
if ((Enc & 0x70) == DW_EH_PE_absptr)
return Addr;
if ((Enc & 0x70) == DW_EH_PE_pcrel)
diff --git a/lld/test/ELF/eh-frame-negative-pcrel-sdata2.s b/lld/test/ELF/eh-frame-negative-pcrel-sdata2.s
new file mode 100644
index 00000000000..30ee8560f0a
--- /dev/null
+++ b/lld/test/ELF/eh-frame-negative-pcrel-sdata2.s
@@ -0,0 +1,85 @@
+# REQUIRES: x86
+
+# Test handling of FDE pc negative relative addressing with DW_EH_PE_sdata2.
+# This situation can arise when .eh_frame is placed after .text.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "SECTIONS { .text : { *(.text) } .eh_frame : { *(.eh_frame) } }" > %t.script
+# RUN: ld.lld --eh-frame-hdr --script %t.script --section-start .text=0x1000 %t.o -o %t
+# RUN: llvm-readobj -s -section-data %t | FileCheck %s
+
+# CHECK: Section {
+# CHECK: Index:
+# CHECK: Name: .eh_frame
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x1001
+# CHECK-NEXT: Offset: 0x1001
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 14000000 00000000 017A5200 01010101
+# CHECK-NEXT: 0010: 1A000000 00000000 0C000000 1C000000
+# CHECK-NEXT: 0020: DFFFFFFF
+# ^
+# DFFFFFFF = _start(0x1000) - PC(.eh_frame(0x1001) + 0x20)
+
+# CHECK: Section {
+# CHECK: Index:
+# CHECK: Name: .eh_frame_hdr
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x1030
+# CHECK-NEXT: Offset: 0x1030
+# CHECK-NEXT: Size: 20
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 011B033B CDFFFFFF 01000000 D0FFFFFF
+# CHECK-NEXT: 0010: E9FFFFFF
+# Header (always 4 bytes): 011B033B
+# CDFFFFFF = .eh_frame(0x1001) - .eh_frame_hdr(0x1030) - 4
+# 01000000 = 1 = the number of FDE pointers in the table.
+# D0FFFFFF = _start(0x1000) - .eh_frame_hdr(0x1030)
+# E9FFFFFF = FDE(.eh_frame(0x1001) + 0x18) - .eh_frame_hdr(0x1030)
+
+.text
+.global _start
+_start:
+ nop
+
+.section .eh_frame, "a"
+ .long 16 # Size
+ .long 0x00 # ID
+ .byte 0x01 # Version.
+
+ .byte 0x7A # Augmentation string: "zR"
+ .byte 0x52
+ .byte 0x00
+
+ .byte 0x01
+
+ .byte 0x01 # LEB128
+ .byte 0x01 # LEB128
+
+ .byte 0x01 # LEB128
+ .byte 0x1A # DW_EH_PE_pcrel | DW_EH_PE_sdata2
+
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+
+ .long 10 # Size
+ .long 24 # ID
+fde:
+ .long _start - fde
+ .word 0
diff --git a/lld/test/ELF/eh-frame-negative-pcrel-sdata4.s b/lld/test/ELF/eh-frame-negative-pcrel-sdata4.s
new file mode 100644
index 00000000000..71b91cf1f4a
--- /dev/null
+++ b/lld/test/ELF/eh-frame-negative-pcrel-sdata4.s
@@ -0,0 +1,85 @@
+# REQUIRES: x86
+
+# Test handling of FDE pc negative relative addressing with DW_EH_PE_sdata4.
+# This situation can arise when .eh_frame is placed after .text.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "SECTIONS { .text : { *(.text) } .eh_frame : { *(.eh_frame) } }" > %t.script
+# RUN: ld.lld --eh-frame-hdr --script %t.script --section-start .text=0x1000 %t.o -o %t
+# RUN: llvm-readobj -s -section-data %t | FileCheck %s
+
+# CHECK: Section {
+# CHECK: Index:
+# CHECK: Name: .eh_frame
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x1001
+# CHECK-NEXT: Offset: 0x1001
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 14000000 00000000 017A5200 01010101
+# CHECK-NEXT: 0010: 1B000000 00000000 0C000000 1C000000
+# CHECK-NEXT: 0020: DFFFFFFF
+# ^
+# DFFFFFFF = _start(0x1000) - PC(.eh_frame(0x1001) + 0x20)
+
+# CHECK: Section {
+# CHECK: Index:
+# CHECK: Name: .eh_frame_hdr
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x1030
+# CHECK-NEXT: Offset: 0x1030
+# CHECK-NEXT: Size: 20
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 011B033B CDFFFFFF 01000000 D0FFFFFF
+# CHECK-NEXT: 0010: E9FFFFFF
+# Header (always 4 bytes): 011B033B
+# CDFFFFFF = .eh_frame(0x1001) - .eh_frame_hdr(0x1030) - 4
+# 01000000 = 1 = the number of FDE pointers in the table.
+# D0FFFFFF = _start(0x1000) - .eh_frame_hdr(0x1030)
+# E9FFFFFF = FDE(.eh_frame(0x1001) + 0x18) - .eh_frame_hdr(0x1030)
+
+.text
+.global _start
+_start:
+ nop
+
+.section .eh_frame, "a"
+ .long 16 # Size
+ .long 0x00 # ID
+ .byte 0x01 # Version.
+
+ .byte 0x7A # Augmentation string: "zR"
+ .byte 0x52
+ .byte 0x00
+
+ .byte 0x01
+
+ .byte 0x01 # LEB128
+ .byte 0x01 # LEB128
+
+ .byte 0x01 # LEB128
+ .byte 0x1B # DW_EH_PE_pcrel | DW_EH_PE_sdata4
+
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+
+ .long 12 # Size
+ .long 24 # ID
+fde:
+ .long _start - fde
+ .long 0
diff --git a/lld/test/ELF/eh-frame-negative-pcrel-sdata8.s b/lld/test/ELF/eh-frame-negative-pcrel-sdata8.s
new file mode 100644
index 00000000000..2c6c9f27cd3
--- /dev/null
+++ b/lld/test/ELF/eh-frame-negative-pcrel-sdata8.s
@@ -0,0 +1,85 @@
+# REQUIRES: x86
+
+# Test handling of FDE pc negative relative addressing with DW_EH_PE_sdata8.
+# This situation can arise when .eh_frame is placed after .text.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "SECTIONS { .text : { *(.text) } .eh_frame : { *(.eh_frame) } }" > %t.script
+# RUN: ld.lld --eh-frame-hdr --script %t.script --section-start .text=0x1000 %t.o -o %t
+# RUN: llvm-readobj -s -section-data %t | FileCheck %s
+
+# CHECK: Section {
+# CHECK: Index:
+# CHECK: Name: .eh_frame
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x1001
+# CHECK-NEXT: Offset: 0x1001
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 14000000 00000000 017A5200 01010101
+# CHECK-NEXT: 0010: 1C000000 00000000 14000000 1C000000
+# CHECK-NEXT: 0020: DFFFFFFF FFFFFFFF
+# ^
+# DFFFFFFF FFFFFFFF = _start(0x1000) - PC(.eh_frame(0x1001) + 0x20)
+
+# CHECK: Section {
+# CHECK: Index:
+# CHECK: Name: .eh_frame_hdr
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x1038
+# CHECK-NEXT: Offset: 0x1038
+# CHECK-NEXT: Size: 20
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 011B033B C5FFFFFF 01000000 C8FFFFFF
+# CHECK-NEXT: 0010: E1FFFFFF
+# Header (always 4 bytes): 011B033B
+# C5FFFFFF = .eh_frame(0x1001) - .eh_frame_hdr(0x1038) - 4
+# 01000000 = 1 = the number of FDE pointers in the table.
+# C8FFFFFF = _start(0x1000) - .eh_frame_hdr(0x1038)
+# E1FFFFFF = FDE(.eh_frame(0x1001) + 0x18) - .eh_frame_hdr(0x1038)
+
+.text
+.global _start
+_start:
+ nop
+
+.section .eh_frame, "a"
+ .long 16 # Size
+ .long 0x00 # ID
+ .byte 0x01 # Version.
+
+ .byte 0x7A # Augmentation string: "zR"
+ .byte 0x52
+ .byte 0x00
+
+ .byte 0x01
+
+ .byte 0x01 # LEB128
+ .byte 0x01 # LEB128
+
+ .byte 0x01 # LEB128
+ .byte 0x1C # DW_EH_PE_pcrel | DW_EH_PE_sdata8
+
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+
+ .long 16 # Size
+ .long 24 # ID
+fde:
+ .quad _start - fde
+ .long 0
OpenPOWER on IntegriCloud