diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -730,7 +730,8 @@ RelExpr X86_64::adjustRelaxExpr(RelType type, const uint8_t *data, RelExpr relExpr) const { - if (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX) + if ((type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX) || + !config->relax) return relExpr; const uint8_t op = data[-2]; const uint8_t modRm = data[-1]; diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -185,6 +185,7 @@ bool pie; bool printGcSections; bool printIcfSections; + bool relax; bool relocatable; bool relrPackDynRelocs; bool saveTemps; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -974,6 +974,7 @@ config->printArchiveStats = args.getLastArgValue(OPT_print_archive_stats); config->printSymbolOrder = args.getLastArgValue(OPT_print_symbol_order); + config->relax = args.hasFlag(OPT_relax, OPT_no_relax, true); config->rpath = getRpath(args); config->relocatable = args.hasArg(OPT_relocatable); config->saveTemps = args.hasArg(OPT_save_temps); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -337,6 +337,10 @@ def print_map: F<"print-map">, HelpText<"Print a link map to the standard output">; +defm relax: BB<"relax", + "Enable target-specific relaxations (default)", + "Disable target-specific relaxations">; + defm reproduce: Eq<"reproduce", "Write a tar file containing input files and command line options to reproduce link">; defm rosegment: BB<"rosegment", diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -308,6 +308,8 @@ Page align sections. .It Fl -no-omagic Do not set the text data sections to be writable, page align sections. +.It Fl -no-relax +Disable target-specific relaxations. This currently disables GOTPCRELX relaxation on x86-64. .It Fl -no-rosegment Do not put read-only non-executable sections in their own segment. .It Fl -no-undefined-version diff --git a/lld/test/ELF/x86-64-gotpc-relax.s b/lld/test/ELF/x86-64-gotpc-relax.s --- a/lld/test/ELF/x86-64-gotpc-relax.s +++ b/lld/test/ELF/x86-64-gotpc-relax.s @@ -4,6 +4,13 @@ # RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOC %s # RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s +# RUN: ld.lld --relax %t.o -o %t2 +# RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM %s + +## --no-relax can disable relaxations. +# RUN: ld.lld --no-relax %t.o -o %t3 +# RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=NORELAX %s + ## There is no relocations. # RELOC: Relocations [ # RELOC: ] @@ -50,6 +57,11 @@ # DISASM-NEXT: jmpq *4119(%rip) # DISASM-NEXT: jmpq *4113(%rip) +# NORELAX-LABEL: : +# NORELAX-COUNT-12: movq +# NORELAX-COUNT-6: callq * +# NORELAX-COUNT-6: jmpq * + .text .globl foo .type foo, @function