[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 {
if (SectionName != Other.SectionName)
return SectionName < Other.SectionName;
if ((Flags & ELF::SHF_STRINGS) != (Other.Flags & ELF::SHF_STRINGS))
return Other.Flags & ELF::SHF_STRINGS;
if (Flags != Other.Flags)
return Flags < Other.Flags;
return EntrySize < Other.EntrySize;
}
};
// Symbols must be assigned to a section with a compatible entry
// size. This map is used to assign unique IDs to sections to
// distinguish between sections with identical names but incompatible entry
// sizes. This can occur when a symbol is explicitly assigned to a
// section, e.g. via __attribute__((section("myname"))).
// Symbols must be assigned to a section with a compatible entry size and
// flags. This map is used to assign unique IDs to sections to distinguish
// between sections with identical names but incompatible entry sizes and/or
// flags. This can occur when a symbol is explicitly assigned to a section,
// e.g. via __attribute__((section("myname"))).
std::map<ELFEntrySizeKey, unsigned> ELFEntrySizeMap;
// This set is used to record the generic mergeable section names seen.
@ -589,6 +589,8 @@ namespace llvm {
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,
unsigned Flags,
unsigned EntrySize);

View File

@ -580,7 +580,7 @@ void MCContext::recordELFMergeableSectionInfo(StringRef SectionName,
unsigned Flags, unsigned UniqueID,
unsigned EntrySize) {
bool IsMergeable = Flags & ELF::SHF_MERGE;
if (IsMergeable && (UniqueID == GenericSectionID))
if (UniqueID == GenericSectionID)
ELFSeenGenericMergeableSections.insert(SectionName);
// 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
; 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
@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
;; for these lines as we want to use --implicit-check-not to reduce the
;; number of checks in this file.
; CHECK: .section .asm_mergeable1,"aMS",@progbits,2
; CHECK-NEXT: .section .asm_nonmergeable1,"a",@progbits
; CHECK-NEXT: .section .asm_mergeable2,"aMS",@progbits,2
; CHECK-NEXT: .section .asm_nonmergeable2,"a",@progbits
; CHECK: .section .asm_mergeable1,"aMS",@progbits,2{{$}}
; CHECK-NEXT: .section .asm_nonmergeable1,"a",@progbits{{$}}
; CHECK-NEXT: .section .asm_mergeable2,"aMS",@progbits,2{{$}}
; CHECK-NEXT: .section .asm_nonmergeable2,"a",@progbits{{$}}
;; Test implicit section assignment for symbols
; CHECK: .section .data,"aw",@progbits,unique,1
@ -21,11 +21,11 @@
;; have the expected properties.
; CHECK: .section .rodata,"a",@progbits,unique,2
; CHECK: implicit_nonmergeable:
; CHECK: .section .rodata.cst4,"aM",@progbits,4
; CHECK: .section .rodata.cst4,"aM",@progbits,4{{$}}
; CHECK: implicit_rodata_cst4:
; CHECK: .section .rodata.cst8,"aM",@progbits,8
; CHECK: .section .rodata.cst8,"aM",@progbits,8{{$}}
; 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:
@implicit_nonmergeable = constant [2 x i16] [i16 1, i16 1]
@ -63,13 +63,13 @@
;; 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"
; CHECK: .section .explicit_basic,"a",@progbits
; CHECK: .section .explicit_basic,"a",@progbits{{$}}
; CHECK: explicit_basic_7:
;; 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"
; CHECK: .section .explicit_initially_nonmergeable,"a",@progbits
; CHECK: .section .explicit_initially_nonmergeable,"a",@progbits{{$}}
; CHECK: explicit_basic_8:
; CHECK: .section .explicit_initially_nonmergeable,"aM",@progbits,4,unique,6
; 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_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: .section .explicit_initially_nonmergeable,"aM",@progbits,4,unique,6
; CHECK: explicit_basic_11:
@ -95,28 +95,28 @@
;; 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"
; CHECK: .section .rodata.cst16,"aM",@progbits,16
; CHECK: .section .rodata.cst16,"aM",@progbits,16{{$}}
; CHECK: explicit_default_2:
;; 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"
; CHECK: .section .debug_str,"MS",@progbits,1
; CHECK: .section .debug_str,"aMS",@progbits,1,unique,[[#U:8]]
; 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"
; CHECK: .section .debug_str,"a",@progbits,unique,8
; CHECK: .section .debug_str,"a",@progbits,unique,[[#U+1]]
; CHECK: explicit_default_4:
;; 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"
;; 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: .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:
@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
;; to a section have been placed into distinct sections with the same name, but
;; 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: .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: .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:
@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}
;; 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: .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 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
;; for a mergeable section. However, as they have no effect it doesn't matter that they
;; 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: .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: .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: .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:
$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)
;; 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: .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 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
;; for a mergeable section. However, as they have no effect it doesn't matter that they
;; 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: .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_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:
$i = comdat any
@ -206,7 +206,7 @@ $i = comdat any
;; Check interaction between symbols that are explicitly assigned
;; 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: explicit_implicit_1:
@ -214,22 +214,22 @@ $i = comdat any
@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"
; CHECK: .section .rodata.str1.1,"a",@progbits,unique,22
; CHECK: .section .rodata.str1.1,"a",@progbits,unique,[[#U+17]]
; CHECK: explicit_implicit_2:
;; 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"
; CHECK: .section .rodata.str1.1,"aMS",@progbits,1
; CHECK: .section .rodata.str1.1,"aMS",@progbits,1{{$}}
; 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:
;; 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_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: implicit_rodata_str2_2:
@ -239,21 +239,21 @@ $i = comdat any
;; 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: .section .asm_nonmergeable1,"a",@progbits
; CHECK: .section .asm_nonmergeable1,"a",@progbits{{$}}
; 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: .section .asm_nonmergeable1,"aMS",@progbits,2,unique,24
; CHECK: .section .asm_nonmergeable1,"aMS",@progbits,2,unique,[[#U+19]]
; 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: .section .asm_nonmergeable2,"aMS",@progbits,2,unique,26
; CHECK: .section .asm_nonmergeable2,"aMS",@progbits,2,unique,[[#U+21]]
; CHECK: explicit_asm_6:
; CHECK: .section .asm_mergeable2,"aMS",@progbits,2
; CHECK: .section .asm_mergeable2,"aMS",@progbits,2{{$}}
; CHECK: explicit_asm_7:
; CHECK: .section .asm_nonmergeable2,"a",@progbits
; CHECK: .section .asm_nonmergeable2,"a",@progbits{{$}}
; CHECK: explicit_asm_8:
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
;; --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.
@ -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: 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
; 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: | 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 \

View File

@ -21,34 +21,36 @@ using namespace llvm::orc;
namespace {
// Adds an object with a debug section to RuntimeDyld and then returns whether
// the debug section was passed to the memory manager.
// Returns whether a non-alloc section was passed to the memory manager.
static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
bool ProcessAllSections) {
class MemoryManagerWrapper : public SectionMemoryManager {
public:
MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
MemoryManagerWrapper(bool &NonAllocSeen) : NonAllocSeen(NonAllocSeen) {}
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
bool IsReadOnly) override {
if (SectionName == ".debug_str")
DebugSeen = true;
// We check for ".note.GNU-stack" here because it is currently the only
// 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(
Size, Alignment, SectionID, SectionName, IsReadOnly);
}
private:
bool &DebugSeen;
bool &NonAllocSeen;
};
bool DebugSectionSeen = false;
bool NonAllocSectionSeen = false;
ExecutionSession ES;
auto &JD = ES.createBareJITDylib("main");
auto Foo = ES.intern("foo");
RTDyldObjectLinkingLayer ObjLayer(ES, [&DebugSectionSeen]() {
return std::make_unique<MemoryManagerWrapper>(DebugSectionSeen);
RTDyldObjectLinkingLayer ObjLayer(ES, [&NonAllocSectionSeen]() {
return std::make_unique<MemoryManagerWrapper>(NonAllocSectionSeen);
});
auto OnResolveDoNothing = [](Expected<SymbolMap> R) {
@ -64,13 +66,16 @@ static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
if (auto Err = ES.endSession())
ES.reportError(std::move(Err));
return DebugSectionSeen;
return NonAllocSectionSeen;
}
TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
LLVMContext Context;
auto M = std::make_unique<Module>("", Context);
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");
auto *GV =
new GlobalVariable(*M, StrConstant->getType(), true,
@ -78,8 +83,6 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
GV->setAlignment(Align(1));
GV->setSection(".debug_str");
// Initialize the native target in case this is the first unit test
// to try to build a TM.
OrcNativeTarget::initialize();
@ -92,9 +95,9 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
EXPECT_FALSE(testSetProcessAllSections(
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))
<< "Expected to see debug section when ProcessAllSections is true";
<< "Expected to see non-alloc section when ProcessAllSections is true";
}
TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {