Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -66,7 +66,7 @@ Configuration *elf::Config; LinkerDriver *elf::Driver; -static void setConfigs(); +static void setConfigs(opt::InputArgList &Args); bool elf::link(ArrayRef Args, bool CanExitEarly, raw_ostream &Error) { @@ -371,7 +371,7 @@ initLLVM(Args); createFiles(Args); inferMachineType(); - setConfigs(); + setConfigs(Args); checkOptions(Args); if (errorCount()) return; @@ -792,7 +792,7 @@ // command line options, but computed based on other Config values. // This function initialize such members. See Config.h for the details // of these values. -static void setConfigs() { +static void setConfigs(opt::InputArgList &Args) { ELFKind Kind = Config->EKind; uint16_t Machine = Config->EMachine; @@ -806,8 +806,10 @@ Config->Endianness = Config->IsLE ? support::endianness::little : support::endianness::big; Config->IsMips64EL = (Kind == ELF64LEKind && Machine == EM_MIPS); - Config->IsRela = + bool IsRelaDefault = Config->Is64 || IsX32 || Config->MipsN32Abi || Machine == EM_PPC; + Config->IsRela = Args.hasFlag(OPT_relocation_format_rela, + OPT_relocation_format_rel, IsRelaDefault); Config->Pic = Config->Pie || Config->Shared; Config->Wordsize = Config->Is64 ? 8 : 4; } Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -339,7 +339,7 @@ auto *P = reinterpret_cast(Buf); Buf += sizeof(RelTy); - if (Config->IsRela) + if (RelTy::IsRela) P->r_addend = getAddend(Rel); // Output section VA is zero for -r, so r_offset is an offset within the @@ -369,7 +369,7 @@ continue; } - if (Config->IsRela) { + if (RelTy::IsRela) { P->r_addend = Sym.getVA(getAddend(Rel)) - Section->getOutputSection()->Addr; } else if (Config->Relocatable) { Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -261,6 +261,12 @@ def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">; +def relocation_format_rel: F<"relocation-format=rel">, + HelpText<"Use Elf_Rel dynamic relocations instead of the default type">; + +def relocation_format_rela: F<"relocation-format=rela">, + HelpText<"Use Elf_Rela dynamic relocations instead of the default type">; + defm retain_symbols_file: Eq<"retain-symbols-file">, HelpText<"Retain only the symbols listed in the file">, MetaVarName<"">; Index: test/ELF/relocatable-rel-rela-mismatch.s =================================================================== --- /dev/null +++ test/ELF/relocatable-rel-rela-mismatch.s @@ -0,0 +1,69 @@ +# REQUIRES: mips +# Check that we correctly write addends with -r if the output use Elf_Rel but +# the input uses Elf_Rela + +# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t-rela.o +# RUN: llvm-objdump --section=.data -s %t-rela.o | FileCheck -check-prefix DATA-RELA %s +# DATA-RELA: Contents of section .data: +# DATA-RELA-NEXT: 0000 00000000 00000000 abcdef00 12345678 .............4Vx + +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-rel.o +# RUN: llvm-objdump --section=.data -s %t-rel.o | FileCheck -check-prefix DATA-REL %s +# Rel should have the relocation value 10 in .data: +# DATA-REL: Contents of section .data: +# DATA-REL-NEXT: 0000 00000000 00000010 abcdef00 12345678 .............4Vx +# ^---- (addend 0x10) + +# RUN: ld.lld -r -o %t-rel-r.o %t-rel.o +# RUN: llvm-readobj -h -s -section-data -relocations %t-rel-r.o | FileCheck -check-prefix RELOCATABLE-REL %s + +# Note: llvm-readobj prints 0x0 as the relocation addend since it doesn't parse +# REL relocations. In order to verify the addend we need to check the contents of .data +# RELOCATABLE-REL: ElfHeader { +# RELOCATABLE-REL: Class: 32-bit +# RELOCATABLE-REL: DataEncoding: BigEndian (0x2) +# RELOCATABLE-REL: Section { +# RELOCATABLE-REL: Name: .data +# RELOCATABLE-REL: SectionData ( +# RELOCATABLE-REL-NEXT: 0000: 00000000 00000010 ABCDEF00 12345678 |.............4Vx| +# ^--- Addend 0x10 for the relocation below +# RELOCATABLE-REL-NEXT: ) + +# RELOCATABLE-REL: Relocations [ +# RELOCATABLE-REL-NEXT: Section ({{.+}}) .rel.data { +# RELOCATABLE-REL-NEXT: 0x0 R_MIPS_64 foo 0x0 +# RELOCATABLE-REL-NEXT: } +# RELOCATABLE-REL-NEXT: ] + + +# RUN: ld.lld -r -o %t-rela-r.o %t-rela.o +# RUN: llvm-readobj -h -s -section-data -relocations %t-rela-r.o | FileCheck -check-prefix RELOCATABLE-RELA %s +# RELOCATABLE-RELA: ElfHeader { +# RELOCATABLE-RELA: Class: 64-bit +# RELOCATABLE-RELA: DataEncoding: BigEndian (0x2) +# RELOCATABLE-RELA: Section { +# RELOCATABLE-RELA: Name: .data +# RELOCATABLE-RELA: SectionData ( +# RELOCATABLE-RELA-NEXT: 0000: 00000000 00000000 ABCDEF00 12345678 |.............4Vx| +# ^--- No addend written here since it is part of Elf_Rela +# RELOCATABLE-RELA: Relocations [ +# RELOCATABLE-RELA-NEXT: Section ({{.+}}) .rela.data { +# RELOCATABLE-RELA-NEXT: 0x0 R_MIPS_64/R_MIPS_NONE/R_MIPS_NONE foo 0x10 +# RELOCATABLE-RELA-NEXT: } +# RELOCATABLE-RELA-NEXT: ] + +# Previously we would lose the addend if the output uses REL but a .foo.rela was being +# copied into the relocatable output. This happenend because addends were only added +# to the output section when Config->IsRela was true instead of checking for RelTy::IsRela. +# We can trigger this situation by using the -relocation-format= flag to not match the input format. +# Check that the relacation addends are copied into the output as expected: +# RUN: ld.lld -r -o %t-forced-rela-r.o -relocation-format=rela %t-rel.o +# RUN: llvm-readobj -h -s -section-data -relocations %t-forced-rela-r.o | FileCheck -check-prefix RELOCATABLE-REL %s +# RUN: ld.lld -r -o %t-forced-rel-r.o -relocation-format=rel %t-rela.o +# RUN: llvm-readobj -h -s -section-data -relocations %t-forced-rel-r.o | FileCheck -check-prefix RELOCATABLE-RELA %s + +.extern foo + +.data +.quad foo + 0x10 +.quad 0xabcdef0012345678