Skip to content

Commit

Permalink
[TargetLoweringObjectFileImpl] Produce .text.hot. instead of .text.ho…
Browse files Browse the repository at this point in the history
…t for -fno-unique-section-names

GNU ld's internal linker script uses (https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=add44f8d5c5c05e08b11e033127a744d61c26aee)

  .text           :
  {
    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
    *(.text.exit .text.exit.*)
    *(.text.startup .text.startup.*)
    *(.text.hot .text.hot.*)
    *(SORT(.text.sorted.*))
    *(.text .stub .text.* .gnu.linkonce.t.*)
    /* .gnu.warning sections are handled specially by elf.em.  */
    *(.gnu.warning)
  }

Because `*(.text.exit .text.exit.*)` is ordered before `*(.text .text.*)`, in a -ffunction-sections build, the C library function `exit` will be placed before other functions.
gold's `-z keep-text-section-prefix` has the same problem.

In lld, `-z keep-text-section-prefix` recognizes `.text.{exit,hot,startup,unlikely,unknown}.*`, but not `.text.{exit,hot,startup,unlikely,unknown}`, to avoid the strange placement problem.

In -fno-function-sections or -fno-unique-section-names mode, a function whose `function_section_prefix` is set to `.exit"`
will go to the output section `.text` instead of `.text.exit` when linked by lld.
To address the problem, append a dot to become `.text.exit.`

Reviewed By: grimar

Differential Revision: https://reviews.llvm.org/D79600
  • Loading branch information
MaskRay committed May 12, 2020
1 parent 363393c commit 6605523
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 2 deletions.
8 changes: 6 additions & 2 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,15 +611,19 @@ getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
Name = getSectionPrefixForGlobal(Kind);
}

bool HasPrefix = false;
if (const auto *F = dyn_cast<Function>(GO)) {
if (Optional<StringRef> Prefix = F->getSectionPrefix())
if (Optional<StringRef> Prefix = F->getSectionPrefix()) {
Name += *Prefix;
HasPrefix = true;
}
}

if (UniqueSectionName) {
Name.push_back('.');
TM.getNameWithPrefix(Name, GO, Mang, /*MayAlwaysUsePrivate*/true);
}
} else if (HasPrefix)
Name.push_back('.');
return Name;
}

Expand Down
6 changes: 6 additions & 0 deletions llvm/test/Transforms/CodeGenPrepare/X86/section.ll
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
; RUN: opt < %s -codegenprepare -S | FileCheck %s
; RUN: llc < %s | FileCheck --check-prefix=ASM1 %s
; RUN: llc < %s -function-sections | FileCheck --check-prefix=ASM2 %s

target triple = "x86_64-pc-linux-gnu"

; This tests that hot/cold functions get correct section prefix assigned

; CHECK: hot_func1{{.*}}!section_prefix ![[HOT_ID:[0-9]+]]
; ASM1: .section .text.hot.,"ax",@progbits
; ASM2: .section .text.hot.hot_func1,"ax",@progbits
; The entry is hot
define void @hot_func1() !prof !15 {
ret void
Expand Down Expand Up @@ -40,6 +44,8 @@ for.end:
; not call site VP metadata (which can exist on value profiled memcpy,
; or possibly left behind after static analysis based devirtualization).
; CHECK: cold_func1{{.*}}!section_prefix ![[COLD_ID:[0-9]+]]
; ASM1: .section .text.unlikely.,"ax",@progbits
; ASM2: .section .text.unlikely.cold_func1,"ax",@progbits
define void @cold_func1() !prof !16 {
call void @hot_func1(), !prof !17
call void @hot_func1(), !prof !17
Expand Down

0 comments on commit 6605523

Please sign in to comment.