Index: lib/MC/ELFObjectWriter.cpp =================================================================== --- lib/MC/ELFObjectWriter.cpp +++ lib/MC/ELFObjectWriter.cpp @@ -537,7 +537,6 @@ case MCSymbolRefExpr::VK_GOT: case MCSymbolRefExpr::VK_PLT: case MCSymbolRefExpr::VK_GOTPCREL: - case MCSymbolRefExpr::VK_Mips_GOT: case MCSymbolRefExpr::VK_PPC_GOT_LO: case MCSymbolRefExpr::VK_PPC_GOT_HI: case MCSymbolRefExpr::VK_PPC_GOT_HA: Index: lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -17,11 +17,21 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCValue.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include using namespace llvm; +// It's difficult to test relocation sort order when we cannot specify the +// symbol in the relocation. This can be used to stop the integrated assembler +// from rewriting the relocations. +static cl::opt AlwaysNeedSymbols( + "mips-relocs-always-need-symbols", cl::init(false), + cl::desc( + "Do not replace symbols used in relocations with section and offset."), + cl::Hidden); + namespace { // A helper structure based on ELFRelocationEntry, used for sorting entries in // the relocation table. @@ -387,30 +397,33 @@ bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, unsigned Type) const { + if (AlwaysNeedSymbols) + return true; + // FIXME: This is extremely conservative. This really needs to use a - // whitelist with a clear explanation for why each realocation needs to + // whitelist with a clear explanation for why each reallocation needs to // point to the symbol, not to the section. switch (Type) { default: return true; + // On REL ABI's (e.g. O32), these relocations form pairs. The pairing is done + // by the static linker by matching the symbol and offset. + // We only see one relocation at a time but it's still safe to relocate with + // the section so long as both relocations make the same decision. + // + // Some older linkers may require the symbol for particular cases. Such cases + // are not supported yet but can be added as required. case ELF::R_MIPS_GOT16: case ELF::R_MIPS16_GOT16: case ELF::R_MICROMIPS_GOT16: - llvm_unreachable("Should have been handled already"); - - // These relocations might be paired with another relocation. The pairing is - // done by the static linker by matching the symbol. Since we only see one - // relocation at a time, we have to force them to relocate with a symbol to - // avoid ending up with a pair where one points to a section and another - // points to a symbol. case ELF::R_MIPS_HI16: case ELF::R_MIPS16_HI16: case ELF::R_MICROMIPS_HI16: case ELF::R_MIPS_LO16: case ELF::R_MIPS16_LO16: case ELF::R_MICROMIPS_LO16: - return true; + return false; case ELF::R_MIPS_16: case ELF::R_MIPS_32: @@ -420,6 +433,8 @@ case ELF::R_MIPS_26: case ELF::R_MIPS_64: case ELF::R_MIPS_GPREL16: + case ELF::R_MIPS_GPREL32: + case ELF::R_MIPS_PC16: return false; } } Index: test/MC/Mips/got-rel-expr.s =================================================================== --- test/MC/Mips/got-rel-expr.s +++ test/MC/Mips/got-rel-expr.s @@ -8,10 +8,10 @@ foo: lw $t0,%got($loc+0x10004)($gp) # CHECK: 0: 8f 88 00 01 lw $8, 1($gp) -# CHECK: 00000000: R_MIPS_GOT16 $loc +# CHECK: 00000000: R_MIPS_GOT16 .data addi $t0,$t0,%lo($loc+0x10004) # CHECK: 4: 21 08 00 04 addi $8, $8, 4 -# CHECK: 00000004: R_MIPS_LO16 $loc +# CHECK: 00000004: R_MIPS_LO16 .data .data $loc: Index: test/MC/Mips/relocation.s =================================================================== --- test/MC/Mips/relocation.s +++ test/MC/Mips/relocation.s @@ -4,6 +4,9 @@ // RUN: | FileCheck -check-prefix=ENCLE -check-prefix=FIXUP %s // RUN: llvm-mc -filetype=obj -triple mipsel-unknown-linux < %s \ // RUN: | llvm-readobj -r | FileCheck -check-prefix=RELOC %s +// RUN: llvm-mc -filetype=obj -triple mips-unknown-linux < %s \ +// RUN: | llvm-readobj -sections -section-data \ +// RUN: | FileCheck -check-prefix=DATA %s // Test that we produce the correct relocation. // FIXME: move more relocation only tests here. @@ -17,9 +20,17 @@ // unknown. // FIXME - Placeholder. Generation method is known but doesn't work. +// DATA-LABEL: Name: .text +// DATA: SectionData ( + +// DATA-NEXT: 0000: 00000004 00000000 00000004 0C000000 .short foo // RELOC: R_MIPS_16 foo - .long foo // RELOC: R_MIPS_32 foo + .short bar // RELOC: R_MIPS_16 .data + +baz: .long foo // RELOC: R_MIPS_32 foo + + .long bar // RELOC: R_MIPS_32 .data // ?????: R_MIPS_REL32 foo @@ -28,36 +39,74 @@ // ENCLE: jal foo # encoding: [A,A,A,0b000011AA] // FIXUP: # fixup A - offset: 0, value: foo, kind: fixup_Mips_26 +// The nop from the jal is at 0x0010 +// DATA-NEXT: 0010: 00000000 0C000001 00000000 24620000 + jal baz // RELOC: R_MIPS_26 .text + // ENCBE: jal baz # encoding: [0b000011AA,A,A,A] + // ENCLE: jal baz # encoding: [A,A,A,0b000011AA] + // FIXUP: # fixup A - offset: 0, value: baz, kind: fixup_Mips_26 + addiu $2, $3, %hi(foo) // RELOC: R_MIPS_HI16 foo // ENCBE: addiu $2, $3, %hi(foo) # encoding: [0x24,0x62,A,A] // ENCLE: addiu $2, $3, %hi(foo) # encoding: [A,A,0x62,0x24] // FIXUP: # fixup A - offset: 0, value: foo@ABS_HI, kind: fixup_Mips_HI16 +// DATA-NEXT: 0020: 24620000 24620000 24620004 24620000 addiu $2, $3, %lo(foo) // RELOC: R_MIPS_LO16 foo // ENCBE: addiu $2, $3, %lo(foo) # encoding: [0x24,0x62,A,A] // ENCLE: addiu $2, $3, %lo(foo) # encoding: [A,A,0x62,0x24] // FIXUP: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16 + addiu $2, $3, %hi(bar) // RELOC: R_MIPS_HI16 .data + // ENCBE: addiu $2, $3, %hi(bar) # encoding: [0x24,0x62,A,A] + // ENCLE: addiu $2, $3, %hi(bar) # encoding: [A,A,0x62,0x24] + // FIXUP: # fixup A - offset: 0, value: bar@ABS_HI, kind: fixup_Mips_HI16 + + addiu $2, $3, %lo(bar) // RELOC: R_MIPS_LO16 .data + // ENCBE: addiu $2, $3, %lo(bar) # encoding: [0x24,0x62,A,A] + // ENCLE: addiu $2, $3, %lo(bar) # encoding: [A,A,0x62,0x24] + // FIXUP: # fixup A - offset: 0, value: bar@ABS_LO, kind: fixup_Mips_LO16 + addiu $2, $3, %gp_rel(foo) // RELOC: R_MIPS_GPREL16 foo // ENCBE: addiu $2, $3, %gp_rel(foo) # encoding: [0x24,0x62,A,A] // ENCLE: addiu $2, $3, %gp_rel(foo) # encoding: [A,A,0x62,0x24] // FIXUP: # fixup A - offset: 0, value: foo@GPREL, kind: fixup_Mips_GPREL +// DATA-NEXT: 0030: 24620004 24620000 24420000 24620000 + addiu $2, $3, %gp_rel(bar) // RELOC: R_MIPS_GPREL16 .data + // ENCBE: addiu $2, $3, %gp_rel(bar) # encoding: [0x24,0x62,A,A] + // ENCLE: addiu $2, $3, %gp_rel(bar) # encoding: [A,A,0x62,0x24] + // FIXUP: # fixup A - offset: 0, value: bar@GPREL, kind: fixup_Mips_GPREL + // ?????: R_MIPS_LITERAL foo addiu $2, $3, %got(foo) // RELOC: R_MIPS_GOT16 foo // ENCBE: addiu $2, $3, %got(foo) # encoding: [0x24,0x62,A,A] // ENCLE: addiu $2, $3, %got(foo) # encoding: [A,A,0x62,0x24] // FIXUP: # fixup A - offset: 0, value: foo@GOT, kind: fixup_Mips_GOT_Local + // %got requires a %lo pair + addiu $2, $2, %lo(foo) + + addiu $2, $3, %got(bar) // RELOC: R_MIPS_GOT16 .data + // ENCBE: addiu $2, $3, %got(bar) # encoding: [0x24,0x62,A,A] + // ENCLE: addiu $2, $3, %got(bar) # encoding: [A,A,0x62,0x24] + // FIXUP: # fixup A - offset: 0, value: bar@GOT, kind: fixup_Mips_GOT_Local +// DATA-NEXT: 0040: 24420004 0000FFBE 24620000 + // %got requires a %lo pair + addiu $2, $2, %lo(bar) .short foo-. // RELOC: R_MIPS_PC16 foo + .short baz-. // RELOC-NOT: R_MIPS_PC16 addiu $2, $3, %call16(foo) // RELOC: R_MIPS_CALL16 foo // ENCBE: addiu $2, $3, %call16(foo) # encoding: [0x24,0x62,A,A] // ENCLE: addiu $2, $3, %call16(foo) # encoding: [A,A,0x62,0x24] // FIXUP: # fixup A - offset: 0, value: foo@GOT_CALL, kind: fixup_Mips_CALL16 + .p2align 4 +// DATA-NEXT: 0050: 00000000 00000000 00000000 00000004 .quad foo // RELOC: R_MIPS_64 foo + .quad bar // RELOC: R_MIPS_64 .data // ?????: R_MIPS_GPREL32 foo // ?????: R_MIPS_UNUSED1 foo @@ -66,6 +115,7 @@ // ?????: R_MIPS_SHIFT5 foo // ?????: R_MIPS_SHIFT6 foo +// DATA-NEXT: 0060: 24620000 24620000 24620000 24620000 addiu $2, $3, %got_disp(foo) // RELOC: R_MIPS_GOT_DISP foo // ENCBE: addiu $2, $3, %got_disp(foo) # encoding: [0x24,0x62,A,A] // ENCLE: addiu $2, $3, %got_disp(foo) # encoding: [A,A,0x62,0x24] @@ -86,6 +136,7 @@ // ENCLE: addiu $2, $3, %got_hi(foo) # encoding: [A,A,0x62,0x24] // FIXUP: # fixup A - offset: 0, value: foo@GOT_HI16, kind: fixup_Mips_GOT_HI16 +// DATA-NEXT: 0070: 24620000 64620000 64620000 24620000 addiu $2, $3, %got_lo(foo) // RELOC: R_MIPS_GOT_LO16 foo // ENCBE: addiu $2, $3, %got_lo(foo) # encoding: [0x24,0x62,A,A] // ENCLE: addiu $2, $3, %got_lo(foo) # encoding: [A,A,0x62,0x24] @@ -113,6 +164,7 @@ // ENCLE: addiu $2, $3, %call_hi(foo) # encoding: [A,A,0x62,0x24] // FIXUP: # fixup A - offset: 0, value: foo@CALL_HI16, kind: fixup_Mips_CALL_HI16 +// DATA-NEXT: 0080: 24620000 24620000 24620000 24620000 addiu $2, $3, %call_lo(foo) // RELOC: R_MIPS_CALL_LO16 foo // ENCBE: addiu $2, $3, %call_lo(foo) # encoding: [0x24,0x62,A,A] // ENCLE: addiu $2, $3, %call_lo(foo) # encoding: [A,A,0x62,0x24] @@ -207,3 +259,9 @@ // FIXME: R_MICROMIPS_* .long foo-. // RELOC: R_MIPS_PC32 foo // .ehword foo // FIXME: R_MIPS_EH foo + + .data + .word 0 +bar: + .word 1 +// DATA-LABEL: Section { Index: test/MC/Mips/sort-relocation-table.s =================================================================== --- test/MC/Mips/sort-relocation-table.s +++ test/MC/Mips/sort-relocation-table.s @@ -1,4 +1,5 @@ -# RUN: llvm-mc -filetype=obj -arch mipsel %s | llvm-readobj -r | FileCheck %s +# RUN: llvm-mc -filetype=obj -arch mipsel %s -mips-relocs-always-need-symbols | \ +# RUN: llvm-readobj -r | FileCheck %s # Test the order of records in the relocation table. # *HI16 and local *GOT16 relocations should be immediately followed by the