[MC][ELF] Emit unique sections for different flags

Global values imply flags such as readable, writable, executable for the
sections that they will be placed in. Currently MC places all such
entries into the same section, using the first set of flags seen. This
can lead to situations in LTO where a writable global is placed in the
same named section as a readable global from another file, and the
section may not be marked writable.

D72194 ensures that mergeable globals with explicit sections are placed
in separate sections with compatible entry size, by emitting the
`unique` assembly syntax where appropriate. This change extends that
approach to include section flags, so that globals with different
section flags are emitted in separate unique sections.

Differential revision: https://reviews.llvm.org/D100944
This commit is contained in:
Tomas Matheson 2021-05-12 18:56:43 +01:00
parent e79e8041c5
commit 165321b3d2
6 changed files with 213 additions and 68 deletions

View File

@ -371,17 +371,17 @@ namespace llvm {
bool operator<(const ELFEntrySizeKey &Other) const { bool operator<(const ELFEntrySizeKey &Other) const {
if (SectionName != Other.SectionName) if (SectionName != Other.SectionName)
return SectionName < Other.SectionName; return SectionName < Other.SectionName;
if ((Flags & ELF::SHF_STRINGS) != (Other.Flags & ELF::SHF_STRINGS)) if (Flags != Other.Flags)
return Other.Flags & ELF::SHF_STRINGS; return Flags < Other.Flags;
return EntrySize < Other.EntrySize; return EntrySize < Other.EntrySize;
} }
}; };
// Symbols must be assigned to a section with a compatible entry // Symbols must be assigned to a section with a compatible entry size and
// size. This map is used to assign unique IDs to sections to // flags. This map is used to assign unique IDs to sections to distinguish
// distinguish between sections with identical names but incompatible entry // between sections with identical names but incompatible entry sizes and/or
// sizes. This can occur when a symbol is explicitly assigned to a // flags. This can occur when a symbol is explicitly assigned to a section,
// section, e.g. via __attribute__((section("myname"))). // e.g. via __attribute__((section("myname"))).
std::map<ELFEntrySizeKey, unsigned> ELFEntrySizeMap; std::map<ELFEntrySizeKey, unsigned> ELFEntrySizeMap;
// This set is used to record the generic mergeable section names seen. // This set is used to record the generic mergeable section names seen.
@ -589,6 +589,8 @@ namespace llvm {
bool isELFGenericMergeableSection(StringRef Name); bool isELFGenericMergeableSection(StringRef Name);
/// Return the unique ID of the section with the given name, flags and entry
/// size, if it exists.
Optional<unsigned> getELFUniqueIDForEntsize(StringRef SectionName, Optional<unsigned> getELFUniqueIDForEntsize(StringRef SectionName,
unsigned Flags, unsigned Flags,
unsigned EntrySize); unsigned EntrySize);

View File

@ -580,7 +580,7 @@ void MCContext::recordELFMergeableSectionInfo(StringRef SectionName,
unsigned Flags, unsigned UniqueID, unsigned Flags, unsigned UniqueID,
unsigned EntrySize) { unsigned EntrySize) {
bool IsMergeable = Flags & ELF::SHF_MERGE; bool IsMergeable = Flags & ELF::SHF_MERGE;
if (IsMergeable && (UniqueID == GenericSectionID)) if (UniqueID == GenericSectionID)
ELFSeenGenericMergeableSections.insert(SectionName); ELFSeenGenericMergeableSections.insert(SectionName);
// For mergeable sections or non-mergeable sections with a generic mergeable // For mergeable sections or non-mergeable sections with a generic mergeable

View File

@ -0,0 +1,140 @@
; Test that global values with the same specified section produces multiple
; sections with different sets of flags, depending on the properties (mutable,
; executable) of the global value.
; RUN: llc < %s | FileCheck %s
; RUN: llc -function-sections < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FNSECTIONS
target triple="x86_64-unknown-unknown-elf"
; Normal function goes in .text, or in it's own named section with -function-sections.
define i32 @fn_text() {
entry:
ret i32 0
}
; CHECK: .text{{$}}
; CHECK-NEXT: .file
; FNSECTIONS: .section .text.fn_text,"ax",@progbits{{$}}
; CHECK-NEXT: .globl fn_text
; CHECK: fn_text:
; A second function placed in .text, to check the behaviour with -function-sections.
; It should be emitted to a new section with a new name, not expected to require unique.
define i32 @fn_text2() {
entry:
ret i32 0
}
; FNSECTIONS: .section .text.fn_text2,"ax",@progbits{{$}}
; CHECK: .globl fn_text2
; CHECK: fn_text2:
; Functions in user defined executable sections
define i32 @fn_s1() section "s1" {
entry:
ret i32 0
}
; CHECK: .section s1,"ax",@progbits{{$}}
; CHECK-NEXT: .globl fn_s1
; CHECK: fn_s1:
define i32 @fn_s2() section "s2" {
entry:
ret i32 0
}
; CHECK: .section s2,"ax",@progbits{{$}}
; CHECK-NEXT: .globl fn_s2
; CHECK: fn_s2:
; A second function in s2 should share the same .section
define i32 @fn2_s2() section "s2" {
entry:
ret i32 0
}
; CHECK-NOT: .section
; CHECK: .globl fn2_s2
; CHECK: fn2_s2:
; Values that share a section name with a function are placed in different sections without executable flag
@rw_s1 = global i32 10, section "s1", align 4
@ro_s2 = constant i32 10, section "s2", align 4
; CHECK: .section s1,"aw",@progbits,unique,[[#UNIQUE_S1_aw:]]
; CHECK-NEXT: .globl rw_s1
; CHECK: rw_s1:
; CHECK: .section s2,"a",@progbits,unique,[[#UNIQUE_S2_a:]]
; CHECK-NEXT: .globl ro_s2
; CHECK: ro_s2:
; Placing another value in the same section with the same flags uses the same unique ID
@rw2_s1 = global i32 10, section "s1", align 4
@ro2_s2 = constant i32 10, section "s2", align 4
; CHECK: .section s1,"aw",@progbits,unique,[[#UNIQUE_S1_aw]]
; CHECK-NEXT: .globl rw2_s1
; CHECK: rw2_s1:
; CHECK: .section s2,"a",@progbits,unique,[[#UNIQUE_S2_a]]
; CHECK-NEXT: .globl ro2_s2
; CHECK: ro2_s2:
; Normal user defined section, first is the generic section, second should be unique
@ro_s3 = constant i32 10, section "s3", align 4
@rw_s3 = global i32 10, section "s3", align 4
; CHECK: .section s3,"a",@progbits{{$}}
; CHECK-NEXT: .globl ro_s3
; CHECK: ro_s3:
; CHECK: .section s3,"aw",@progbits,unique,[[#U:]]
; CHECK-NEXT: .globl rw_s3
; CHECK: rw_s3:
; Values declared without explicit sections go into compatible default sections and don't require unique
@rw_nosec = global i32 10, align 4
@ro_nosec = constant i32 10, align 4
; CHECK: .data{{$}}
; CHECK-NEXT: .globl rw_nosec
; CHECK: rw_nosec:
; CHECK: .section .rodata,"a",@progbits{{$}}
; CHECK-NEXT: .globl ro_nosec
; CHECK: ro_nosec:
; Explicitly placed in .rodata with writeable set. The writable section should be uniqued, not the default ro section, even if it comes first.
@rw_rodata = global [2 x i32] zeroinitializer, section ".rodata", align 4
@ro_rodata = constant [2 x i32] zeroinitializer, section ".rodata", align 4
; CHECK: .section .rodata,"aw",@progbits,unique,[[#U+1]]{{$}}
; CHECK-NEXT: .globl rw_rodata{{$}}
; CHECK: rw_rodata:
; CHECK: .section .rodata,"a",@progbits{{$}}
; CHECK-NEXT: .globl ro_rodata{{$}}
; CHECK: ro_rodata:
; Writable symbols in writable default sections; no need to unique
@w_sdata = global [4 x i32] zeroinitializer, section ".sdata", align 4
@w_sbss = global [4 x i32] zeroinitializer, section ".sbss", align 4
; CHECK: .section .sdata,"aw",@progbits{{$}}
; CHECK-NEXT: .globl w_sdata{{$}}
; CHECK: w_sdata:
; CHECK: .section .sbss,"aw",@nobits{{$}}
; CHECK-NEXT: .globl w_sbss{{$}}
; CHECK: w_sbss:
; Multiple .text sections are emitted for read-only and read-write sections using .text name.
@rw_text = global i32 10, section ".text", align 4
@ro_text = constant i32 10, section ".text", align 4
; CHECK: .section .text,"aw",@progbits,unique,[[#U+2]]
; CHECK-NEXT: .globl rw_text
; CHECK: rw_text:
; CHECK: .section .text,"a",@progbits,unique,[[#U+3]]
; CHECK-NEXT: .globl ro_text
; CHECK: ro_text:
; A read-only .data section is emitted
@ro_data = constant i32 10, section ".data", align 4
; CHECK: .section .data,"a",@progbits,unique,[[#U+4]]
; CHECK-NEXT: .globl ro_data
; CHECK: ro_data:
; TLS and non-TLS symbols cannot live in the same section
@tls_var = thread_local global i32 10, section "s4", align 4
@non_tls_var = global i32 10, section "s4", align 4
; CHECK: .section s4,"awT",@progbits{{$}}
; CHECK-NEXT: .globl tls_var
; CHECK: tls_var:
; CHECK: .section s4,"aw",@progbits,unique,[[#U+5]]
; CHECK-NEXT: .globl non_tls_var
; CHECK: non_tls_var:

View File

@ -7,7 +7,7 @@
; small data section. Also test that explicitly placing something in the small ; small data section. Also test that explicitly placing something in the small
; data section uses %gp_rel addressing mode. ; data section uses %gp_rel addressing mode.
@a = global [2 x i32] zeroinitializer, section ".rodata", align 4 @a = constant [2 x i32] zeroinitializer, section ".rodata", align 4
@b = global [4 x i32] zeroinitializer, section ".sdata", align 4 @b = global [4 x i32] zeroinitializer, section ".sdata", align 4
@c = global [4 x i32] zeroinitializer, section ".sbss", align 4 @c = global [4 x i32] zeroinitializer, section ".sbss", align 4

View File

@ -4,10 +4,10 @@
;; Several sections are created via inline assembly. We add checks ;; Several sections are created via inline assembly. We add checks
;; for these lines as we want to use --implicit-check-not to reduce the ;; for these lines as we want to use --implicit-check-not to reduce the
;; number of checks in this file. ;; number of checks in this file.
; CHECK: .section .asm_mergeable1,"aMS",@progbits,2 ; CHECK: .section .asm_mergeable1,"aMS",@progbits,2{{$}}
; CHECK-NEXT: .section .asm_nonmergeable1,"a",@progbits ; CHECK-NEXT: .section .asm_nonmergeable1,"a",@progbits{{$}}
; CHECK-NEXT: .section .asm_mergeable2,"aMS",@progbits,2 ; CHECK-NEXT: .section .asm_mergeable2,"aMS",@progbits,2{{$}}
; CHECK-NEXT: .section .asm_nonmergeable2,"a",@progbits ; CHECK-NEXT: .section .asm_nonmergeable2,"a",@progbits{{$}}
;; Test implicit section assignment for symbols ;; Test implicit section assignment for symbols
; CHECK: .section .data,"aw",@progbits,unique,1 ; CHECK: .section .data,"aw",@progbits,unique,1
@ -21,11 +21,11 @@
;; have the expected properties. ;; have the expected properties.
; CHECK: .section .rodata,"a",@progbits,unique,2 ; CHECK: .section .rodata,"a",@progbits,unique,2
; CHECK: implicit_nonmergeable: ; CHECK: implicit_nonmergeable:
; CHECK: .section .rodata.cst4,"aM",@progbits,4 ; CHECK: .section .rodata.cst4,"aM",@progbits,4{{$}}
; CHECK: implicit_rodata_cst4: ; CHECK: implicit_rodata_cst4:
; CHECK: .section .rodata.cst8,"aM",@progbits,8 ; CHECK: .section .rodata.cst8,"aM",@progbits,8{{$}}
; CHECK: implicit_rodata_cst8: ; CHECK: implicit_rodata_cst8:
; CHECK: .section .rodata.str4.4,"aMS",@progbits,4 ; CHECK: .section .rodata.str4.4,"aMS",@progbits,4{{$}}
; CHECK: implicit_rodata_str4_4: ; CHECK: implicit_rodata_str4_4:
@implicit_nonmergeable = constant [2 x i16] [i16 1, i16 1] @implicit_nonmergeable = constant [2 x i16] [i16 1, i16 1]
@ -63,13 +63,13 @@
;; Assign a compatible mergeable global to the previous section. ;; Assign a compatible mergeable global to the previous section.
@explicit_basic_6 = unnamed_addr constant [2 x i32] [i32 1, i32 0], section ".explicit_basic" @explicit_basic_6 = unnamed_addr constant [2 x i32] [i32 1, i32 0], section ".explicit_basic"
; CHECK: .section .explicit_basic,"a",@progbits ; CHECK: .section .explicit_basic,"a",@progbits{{$}}
; CHECK: explicit_basic_7: ; CHECK: explicit_basic_7:
;; Assign a symbol with an incompatible entsize (non-mergeable) to a mergeable section created explicitly. ;; Assign a symbol with an incompatible entsize (non-mergeable) to a mergeable section created explicitly.
@explicit_basic_7 = constant [2 x i16] [i16 1, i16 1], section ".explicit_basic" @explicit_basic_7 = constant [2 x i16] [i16 1, i16 1], section ".explicit_basic"
; CHECK: .section .explicit_initially_nonmergeable,"a",@progbits ; CHECK: .section .explicit_initially_nonmergeable,"a",@progbits{{$}}
; CHECK: explicit_basic_8: ; CHECK: explicit_basic_8:
; CHECK: .section .explicit_initially_nonmergeable,"aM",@progbits,4,unique,6 ; CHECK: .section .explicit_initially_nonmergeable,"aM",@progbits,4,unique,6
; CHECK: explicit_basic_9: ; CHECK: explicit_basic_9:
@ -78,7 +78,7 @@
@explicit_basic_8 = constant [2 x i16] [i16 1, i16 1], section ".explicit_initially_nonmergeable" @explicit_basic_8 = constant [2 x i16] [i16 1, i16 1], section ".explicit_initially_nonmergeable"
@explicit_basic_9 = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit_initially_nonmergeable" @explicit_basic_9 = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit_initially_nonmergeable"
; CHECK: .section .explicit_initially_nonmergeable,"a",@progbits ; CHECK: .section .explicit_initially_nonmergeable,"a",@progbits{{$}}
; CHECK: explicit_basic_10: ; CHECK: explicit_basic_10:
; CHECK: .section .explicit_initially_nonmergeable,"aM",@progbits,4,unique,6 ; CHECK: .section .explicit_initially_nonmergeable,"aM",@progbits,4,unique,6
; CHECK: explicit_basic_11: ; CHECK: explicit_basic_11:
@ -95,28 +95,28 @@
;; Assign an incompatible (non-mergeable) symbol to a "default" mergeable section. ;; Assign an incompatible (non-mergeable) symbol to a "default" mergeable section.
@explicit_default_1 = constant [2 x i64] [i64 1, i64 1], section ".rodata.cst16" @explicit_default_1 = constant [2 x i64] [i64 1, i64 1], section ".rodata.cst16"
; CHECK: .section .rodata.cst16,"aM",@progbits,16 ; CHECK: .section .rodata.cst16,"aM",@progbits,16{{$}}
; CHECK: explicit_default_2: ; CHECK: explicit_default_2:
;; Assign a compatible global to a "default" mergeable section. ;; Assign a compatible global to a "default" mergeable section.
@explicit_default_2 = unnamed_addr constant [2 x i64] [i64 1, i64 1], section ".rodata.cst16" @explicit_default_2 = unnamed_addr constant [2 x i64] [i64 1, i64 1], section ".rodata.cst16"
; CHECK: .section .debug_str,"MS",@progbits,1 ; CHECK: .section .debug_str,"aMS",@progbits,1,unique,[[#U:8]]
; CHECK: explicit_default_3: ; CHECK: explicit_default_3:
;; Non-allocatable "default" sections can have allocatable mergeable symbols with compatible entry sizes assigned to them. ;; Non-allocatable "default" sections can be re-emitted with allocatable flag and uniqued
@explicit_default_3 = unnamed_addr constant [2 x i8] [i8 1, i8 0], section ".debug_str" @explicit_default_3 = unnamed_addr constant [2 x i8] [i8 1, i8 0], section ".debug_str"
; CHECK: .section .debug_str,"a",@progbits,unique,8 ; CHECK: .section .debug_str,"a",@progbits,unique,[[#U+1]]
; CHECK: explicit_default_4: ; CHECK: explicit_default_4:
;; Non-allocatable "default" sections cannot have allocatable mergeable symbols with incompatible (non-mergeable) entry sizes assigned to them. ;; Non-allocatable "default" sections cannot have allocatable mergeable symbols with incompatible (non-mergeable) entry sizes assigned to them.
@explicit_default_4 = constant [2 x i16] [i16 1, i16 1], section ".debug_str" @explicit_default_4 = constant [2 x i16] [i16 1, i16 1], section ".debug_str"
;; Test implicit section assignment for globals with associated globals. ;; Test implicit section assignment for globals with associated globals.
; CHECK: .section .rodata.cst4,"aMo",@progbits,4,implicit_rodata_cst4,unique,9 ; CHECK: .section .rodata.cst4,"aMo",@progbits,4,implicit_rodata_cst4,unique,[[#U+2]]
; CHECK: implicit_rodata_cst4_assoc: ; CHECK: implicit_rodata_cst4_assoc:
; CHECK: .section .rodata.cst8,"aMo",@progbits,8,implicit_rodata_cst4,unique,10 ; CHECK: .section .rodata.cst8,"aMo",@progbits,8,implicit_rodata_cst4,unique,[[#U+3]]
; CHECK: implicit_rodata_cst8_assoc: ; CHECK: implicit_rodata_cst8_assoc:
@implicit_rodata_cst4_assoc = unnamed_addr constant [2 x i16] [i16 1, i16 1], !associated !4 @implicit_rodata_cst4_assoc = unnamed_addr constant [2 x i16] [i16 1, i16 1], !associated !4
@ -125,11 +125,11 @@
;; Check that globals with associated globals that are explicitly assigned ;; Check that globals with associated globals that are explicitly assigned
;; to a section have been placed into distinct sections with the same name, but ;; to a section have been placed into distinct sections with the same name, but
;; different entry sizes. ;; different entry sizes.
; CHECK: .section .explicit,"aMo",@progbits,4,implicit_rodata_cst4,unique,11 ; CHECK: .section .explicit,"aMo",@progbits,4,implicit_rodata_cst4,unique,[[#U+4]]
; CHECK: explicit_assoc_1: ; CHECK: explicit_assoc_1:
; CHECK: .section .explicit,"aMo",@progbits,4,implicit_rodata_cst4,unique,12 ; CHECK: .section .explicit,"aMo",@progbits,4,implicit_rodata_cst4,unique,[[#U+5]]
; CHECK: explicit_assoc_2: ; CHECK: explicit_assoc_2:
; CHECK: .section .explicit,"aMo",@progbits,8,implicit_rodata_cst4,unique,13 ; CHECK: .section .explicit,"aMo",@progbits,8,implicit_rodata_cst4,unique,[[#U+6]]
; CHECK: explicit_assoc_3: ; CHECK: explicit_assoc_3:
@explicit_assoc_1 = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit", !associated !4 @explicit_assoc_1 = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit", !associated !4
@ -139,9 +139,9 @@
!4 = !{[2 x i16]* @implicit_rodata_cst4} !4 = !{[2 x i16]* @implicit_rodata_cst4}
;; Test implicit section assignment for globals in distinct comdat groups. ;; Test implicit section assignment for globals in distinct comdat groups.
; CHECK: .section .rodata.cst4,"aGM",@progbits,4,f,comdat,unique,14 ; CHECK: .section .rodata.cst4,"aGM",@progbits,4,f,comdat,unique,[[#U+7]]
; CHECK: implicit_rodata_cst4_comdat: ; CHECK: implicit_rodata_cst4_comdat:
; CHECK: .section .rodata.cst8,"aGM",@progbits,8,g,comdat,unique,15 ; CHECK: .section .rodata.cst8,"aGM",@progbits,8,g,comdat,unique,[[#U+8]]
; CHECK: implicit_rodata_cst8_comdat: ; CHECK: implicit_rodata_cst8_comdat:
;; Check that globals in distinct comdat groups that are explicitly assigned ;; Check that globals in distinct comdat groups that are explicitly assigned
@ -151,13 +151,13 @@
;; appear incorrect as comdats are not taken into account when looking up the unique ID ;; appear incorrect as comdats are not taken into account when looking up the unique ID
;; for a mergeable section. However, as they have no effect it doesn't matter that they ;; for a mergeable section. However, as they have no effect it doesn't matter that they
;; are incorrect. ;; are incorrect.
; CHECK: .section .explicit_comdat_distinct,"aM",@progbits,4,unique,16 ; CHECK: .section .explicit_comdat_distinct,"aM",@progbits,4,unique,[[#U+9]]
; CHECK: explicit_comdat_distinct_supply_uid: ; CHECK: explicit_comdat_distinct_supply_uid:
; CHECK: .section .explicit_comdat_distinct,"aGM",@progbits,4,f,comdat,unique,16 ; CHECK: .section .explicit_comdat_distinct,"aGM",@progbits,4,f,comdat,unique,[[#U+10]]
; CHECK: explicit_comdat_distinct1: ; CHECK: explicit_comdat_distinct1:
; CHECK: .section .explicit_comdat_distinct,"aGM",@progbits,4,g,comdat,unique,16 ; CHECK: .section .explicit_comdat_distinct,"aGM",@progbits,4,g,comdat,unique,[[#U+10]]
; CHECK: explicit_comdat_distinct2: ; CHECK: explicit_comdat_distinct2:
; CHECK: .section .explicit_comdat_distinct,"aGM",@progbits,8,h,comdat,unique,17 ; CHECK: .section .explicit_comdat_distinct,"aGM",@progbits,8,h,comdat,unique,[[#U+11]]
; CHECK: explicit_comdat_distinct3: ; CHECK: explicit_comdat_distinct3:
$f = comdat any $f = comdat any
@ -173,9 +173,9 @@ $h = comdat any
@explicit_comdat_distinct3 = unnamed_addr constant [2 x i32] [i32 1, i32 1], section ".explicit_comdat_distinct", comdat($h) @explicit_comdat_distinct3 = unnamed_addr constant [2 x i32] [i32 1, i32 1], section ".explicit_comdat_distinct", comdat($h)
;; Test implicit section assignment for globals in the same comdat group. ;; Test implicit section assignment for globals in the same comdat group.
; CHECK: .section .rodata.cst4,"aGM",@progbits,4,i,comdat,unique,18 ; CHECK: .section .rodata.cst4,"aGM",@progbits,4,i,comdat,unique,[[#U+12]]
; CHECK: implicit_rodata_cst4_same_comdat: ; CHECK: implicit_rodata_cst4_same_comdat:
; CHECK: .section .rodata.cst8,"aGM",@progbits,8,i,comdat,unique,19 ; CHECK: .section .rodata.cst8,"aGM",@progbits,8,i,comdat,unique,[[#U+13]]
; CHECK: implicit_rodata_cst8_same_comdat: ; CHECK: implicit_rodata_cst8_same_comdat:
;; Check that globals in the same comdat group that are explicitly assigned ;; Check that globals in the same comdat group that are explicitly assigned
@ -185,12 +185,12 @@ $h = comdat any
;; appear incorrect as comdats are not taken into account when looking up the unique ID ;; appear incorrect as comdats are not taken into account when looking up the unique ID
;; for a mergeable section. However, as they have no effect it doesn't matter that they ;; for a mergeable section. However, as they have no effect it doesn't matter that they
;; are incorrect. ;; are incorrect.
; CHECK: .section .explicit_comdat_same,"aM",@progbits,4,unique,20 ; CHECK: .section .explicit_comdat_same,"aM",@progbits,4,unique,[[#U+14]]
; CHECK: explicit_comdat_same_supply_uid: ; CHECK: explicit_comdat_same_supply_uid:
; CHECK: .section .explicit_comdat_same,"aGM",@progbits,4,i,comdat,unique,20 ; CHECK: .section .explicit_comdat_same,"aGM",@progbits,4,i,comdat,unique,[[#U+15]]
; CHECK: explicit_comdat_same1: ; CHECK: explicit_comdat_same1:
; CHECK: explicit_comdat_same2: ; CHECK: explicit_comdat_same2:
; CHECK: .section .explicit_comdat_same,"aGM",@progbits,8,i,comdat,unique,21 ; CHECK: .section .explicit_comdat_same,"aGM",@progbits,8,i,comdat,unique,[[#U+16]]
; CHECK: explicit_comdat_same3: ; CHECK: explicit_comdat_same3:
$i = comdat any $i = comdat any
@ -206,7 +206,7 @@ $i = comdat any
;; Check interaction between symbols that are explicitly assigned ;; Check interaction between symbols that are explicitly assigned
;; to a section and implicitly assigned symbols. ;; to a section and implicitly assigned symbols.
; CHECK: .section .rodata.str1.1,"aMS",@progbits,1 ; CHECK: .section .rodata.str1.1,"aMS",@progbits,1{{$}}
; CHECK: implicit_rodata_str1_1: ; CHECK: implicit_rodata_str1_1:
; CHECK: explicit_implicit_1: ; CHECK: explicit_implicit_1:
@ -214,22 +214,22 @@ $i = comdat any
@implicit_rodata_str1_1 = unnamed_addr constant [2 x i8] [i8 1, i8 0] @implicit_rodata_str1_1 = unnamed_addr constant [2 x i8] [i8 1, i8 0]
@explicit_implicit_1 = unnamed_addr constant [2 x i8] [i8 1, i8 0], section ".rodata.str1.1" @explicit_implicit_1 = unnamed_addr constant [2 x i8] [i8 1, i8 0], section ".rodata.str1.1"
; CHECK: .section .rodata.str1.1,"a",@progbits,unique,22 ; CHECK: .section .rodata.str1.1,"a",@progbits,unique,[[#U+17]]
; CHECK: explicit_implicit_2: ; CHECK: explicit_implicit_2:
;; Assign an incompatible symbol (non-mergeable) to an existing mergeable section created implicitly. ;; Assign an incompatible symbol (non-mergeable) to an existing mergeable section created implicitly.
@explicit_implicit_2 = constant [2 x i16] [i16 1, i16 1], section ".rodata.str1.1" @explicit_implicit_2 = constant [2 x i16] [i16 1, i16 1], section ".rodata.str1.1"
; CHECK: .section .rodata.str1.1,"aMS",@progbits,1 ; CHECK: .section .rodata.str1.1,"aMS",@progbits,1{{$}}
; CHECK: explicit_implicit_3: ; CHECK: explicit_implicit_3:
; CHECK: .section .rodata.str1.1,"a",@progbits,unique,22 ; CHECK: .section .rodata.str1.1,"a",@progbits,unique,[[#U+17]]
; CHECK: explicit_implicit_4: ; CHECK: explicit_implicit_4:
;; Assign compatible globals to the previously created sections. ;; Assign compatible globals to the previously created sections.
@explicit_implicit_3 = unnamed_addr constant [2 x i8] [i8 1, i8 0], section ".rodata.str1.1" @explicit_implicit_3 = unnamed_addr constant [2 x i8] [i8 1, i8 0], section ".rodata.str1.1"
@explicit_implicit_4 = constant [2 x i16] [i16 1, i16 1], section ".rodata.str1.1" @explicit_implicit_4 = constant [2 x i16] [i16 1, i16 1], section ".rodata.str1.1"
; CHECK: .section .rodata.str2.2,"aMS",@progbits,2 ; CHECK: .section .rodata.str2.2,"aMS",@progbits,2{{$}}
; CHECK: explicit_implicit_5: ; CHECK: explicit_implicit_5:
; CHECK: implicit_rodata_str2_2: ; CHECK: implicit_rodata_str2_2:
@ -239,21 +239,21 @@ $i = comdat any
;; Check the interaction with inline asm. ;; Check the interaction with inline asm.
; CHECK: .section .asm_mergeable1,"aMS",@progbits,2 ; CHECK: .section .asm_mergeable1,"aMS",@progbits,2{{$}}
; CHECK: explicit_asm_1: ; CHECK: explicit_asm_1:
; CHECK: .section .asm_nonmergeable1,"a",@progbits ; CHECK: .section .asm_nonmergeable1,"a",@progbits{{$}}
; CHECK: explicit_asm_2: ; CHECK: explicit_asm_2:
; CHECK: .section .asm_mergeable1,"aM",@progbits,4,unique,23 ; CHECK: .section .asm_mergeable1,"aM",@progbits,4,unique,[[#U+18]]
; CHECK: explicit_asm_3: ; CHECK: explicit_asm_3:
; CHECK: .section .asm_nonmergeable1,"aMS",@progbits,2,unique,24 ; CHECK: .section .asm_nonmergeable1,"aMS",@progbits,2,unique,[[#U+19]]
; CHECK: explicit_asm_4: ; CHECK: explicit_asm_4:
; CHECK: .section .asm_mergeable2,"aM",@progbits,4,unique,25 ; CHECK: .section .asm_mergeable2,"aM",@progbits,4,unique,[[#U+20]]
; CHECK: explicit_asm_5: ; CHECK: explicit_asm_5:
; CHECK: .section .asm_nonmergeable2,"aMS",@progbits,2,unique,26 ; CHECK: .section .asm_nonmergeable2,"aMS",@progbits,2,unique,[[#U+21]]
; CHECK: explicit_asm_6: ; CHECK: explicit_asm_6:
; CHECK: .section .asm_mergeable2,"aMS",@progbits,2 ; CHECK: .section .asm_mergeable2,"aMS",@progbits,2{{$}}
; CHECK: explicit_asm_7: ; CHECK: explicit_asm_7:
; CHECK: .section .asm_nonmergeable2,"a",@progbits ; CHECK: .section .asm_nonmergeable2,"a",@progbits{{$}}
; CHECK: explicit_asm_8: ; CHECK: explicit_asm_8:
module asm ".section .asm_mergeable1,\22aMS\22,@progbits,2" module asm ".section .asm_mergeable1,\22aMS\22,@progbits,2"
@ -277,7 +277,7 @@ module asm ".section .asm_nonmergeable2,\22a\22,@progbits"
;; A .note.GNU-stack section is created implicitly. We add a check for this as we want to use ;; A .note.GNU-stack section is created implicitly. We add a check for this as we want to use
;; --implicit-check-not to reduce the number of checks in this file. ;; --implicit-check-not to reduce the number of checks in this file.
; CHECK: .section ".note.GNU-stack","",@progbits ; CHECK: .section ".note.GNU-stack","",@progbits{{$}}
;; --no-integrated-as avoids the use of ",unique," for compatibility with older binutils. ;; --no-integrated-as avoids the use of ",unique," for compatibility with older binutils.
@ -294,7 +294,7 @@ module asm ".section .asm_nonmergeable2,\22a\22,@progbits"
; RUN: echo '@explicit = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit"' > %t.no_i_as.ll ; RUN: echo '@explicit = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit"' > %t.no_i_as.ll
; RUN: llc < %t.no_i_as.ll -mtriple=x86_64 --no-integrated-as -binutils-version=2.34 2>&1 \ ; RUN: llc < %t.no_i_as.ll -mtriple=x86_64 --no-integrated-as -binutils-version=2.34 2>&1 \
; RUN: | FileCheck %s --check-prefix=NO-I-AS-OLD ; RUN: | FileCheck %s --check-prefix=NO-I-AS-OLD
; NO-I-AS-OLD: .section .explicit,"a",@progbits ; NO-I-AS-OLD: .section .explicit,"a",@progbits{{$}}
; RUN: llc < %t.no_i_as.ll -mtriple=x86_64 --no-integrated-as -binutils-version=2.35 2>&1 \ ; RUN: llc < %t.no_i_as.ll -mtriple=x86_64 --no-integrated-as -binutils-version=2.35 2>&1 \
; RUN: | FileCheck %s --check-prefix=NO-I-AS-NEW ; RUN: | FileCheck %s --check-prefix=NO-I-AS-NEW
; RUN: llc < %t.no_i_as.ll -mtriple=x86_64 --no-integrated-as -binutils-version=none 2>&1 \ ; RUN: llc < %t.no_i_as.ll -mtriple=x86_64 --no-integrated-as -binutils-version=none 2>&1 \

View File

@ -21,34 +21,36 @@ using namespace llvm::orc;
namespace { namespace {
// Adds an object with a debug section to RuntimeDyld and then returns whether // Returns whether a non-alloc section was passed to the memory manager.
// the debug section was passed to the memory manager.
static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj, static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
bool ProcessAllSections) { bool ProcessAllSections) {
class MemoryManagerWrapper : public SectionMemoryManager { class MemoryManagerWrapper : public SectionMemoryManager {
public: public:
MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {} MemoryManagerWrapper(bool &NonAllocSeen) : NonAllocSeen(NonAllocSeen) {}
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName, unsigned SectionID, StringRef SectionName,
bool IsReadOnly) override { bool IsReadOnly) override {
if (SectionName == ".debug_str") // We check for ".note.GNU-stack" here because it is currently the only
DebugSeen = true; // non-alloc section seen in the module. If this changes in future any
// other non-alloc section would do here.
if (SectionName == ".note.GNU-stack")
NonAllocSeen = true;
return SectionMemoryManager::allocateDataSection( return SectionMemoryManager::allocateDataSection(
Size, Alignment, SectionID, SectionName, IsReadOnly); Size, Alignment, SectionID, SectionName, IsReadOnly);
} }
private: private:
bool &DebugSeen; bool &NonAllocSeen;
}; };
bool DebugSectionSeen = false; bool NonAllocSectionSeen = false;
ExecutionSession ES; ExecutionSession ES;
auto &JD = ES.createBareJITDylib("main"); auto &JD = ES.createBareJITDylib("main");
auto Foo = ES.intern("foo"); auto Foo = ES.intern("foo");
RTDyldObjectLinkingLayer ObjLayer(ES, [&DebugSectionSeen]() { RTDyldObjectLinkingLayer ObjLayer(ES, [&NonAllocSectionSeen]() {
return std::make_unique<MemoryManagerWrapper>(DebugSectionSeen); return std::make_unique<MemoryManagerWrapper>(NonAllocSectionSeen);
}); });
auto OnResolveDoNothing = [](Expected<SymbolMap> R) { auto OnResolveDoNothing = [](Expected<SymbolMap> R) {
@ -64,13 +66,16 @@ static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
if (auto Err = ES.endSession()) if (auto Err = ES.endSession())
ES.reportError(std::move(Err)); ES.reportError(std::move(Err));
return DebugSectionSeen; return NonAllocSectionSeen;
} }
TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
LLVMContext Context; LLVMContext Context;
auto M = std::make_unique<Module>("", Context); auto M = std::make_unique<Module>("", Context);
M->setTargetTriple("x86_64-unknown-linux-gnu"); M->setTargetTriple("x86_64-unknown-linux-gnu");
// These values are only here to ensure that the module is non-empty.
// They are no longer relevant to the test.
Constant *StrConstant = ConstantDataArray::getString(Context, "forty-two"); Constant *StrConstant = ConstantDataArray::getString(Context, "forty-two");
auto *GV = auto *GV =
new GlobalVariable(*M, StrConstant->getType(), true, new GlobalVariable(*M, StrConstant->getType(), true,
@ -78,8 +83,6 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
GV->setAlignment(Align(1)); GV->setAlignment(Align(1));
GV->setSection(".debug_str");
// Initialize the native target in case this is the first unit test // Initialize the native target in case this is the first unit test
// to try to build a TM. // to try to build a TM.
OrcNativeTarget::initialize(); OrcNativeTarget::initialize();
@ -92,9 +95,9 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
EXPECT_FALSE(testSetProcessAllSections( EXPECT_FALSE(testSetProcessAllSections(
MemoryBuffer::getMemBufferCopy(Obj->getBuffer()), false)) MemoryBuffer::getMemBufferCopy(Obj->getBuffer()), false))
<< "Debug section seen despite ProcessAllSections being false"; << "Non-alloc section seen despite ProcessAllSections being false";
EXPECT_TRUE(testSetProcessAllSections(std::move(Obj), true)) EXPECT_TRUE(testSetProcessAllSections(std::move(Obj), true))
<< "Expected to see debug section when ProcessAllSections is true"; << "Expected to see non-alloc section when ProcessAllSections is true";
} }
TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) { TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {