diff options
-rw-r--r-- | llvm/lib/MC/ELFObjectWriter.cpp | 37 | ||||
-rw-r--r-- | llvm/test/MC/ELF/type.s | 197 |
2 files changed, 233 insertions, 1 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 6a48d62c8e1..9490a9941ac 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -532,6 +532,41 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, } } +static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) { + uint8_t Type = newType; + + // Propagation rules: + // IFUNC > FUNC > OBJECT > NOTYPE + // TLS_OBJECT > OBJECT > NOTYPE + // + // dont let the new type degrade the old type + switch (origType) { + default: + break; + case ELF::STT_GNU_IFUNC: + if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT || + Type == ELF::STT_NOTYPE || Type == ELF::STT_TLS) + Type = ELF::STT_GNU_IFUNC; + break; + case ELF::STT_FUNC: + if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE || + Type == ELF::STT_TLS) + Type = ELF::STT_FUNC; + break; + case ELF::STT_OBJECT: + if (Type == ELF::STT_NOTYPE) + Type = ELF::STT_OBJECT; + break; + case ELF::STT_TLS: + if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE || + Type == ELF::STT_GNU_IFUNC || Type == ELF::STT_FUNC) + Type = ELF::STT_TLS; + break; + } + + return Type; +} + void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, ELFSymbolData &MSD, @@ -545,7 +580,7 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, // Binding and Type share the same byte as upper and lower nibbles uint8_t Binding = MCELF::GetBinding(OrigData); - uint8_t Type = MCELF::GetType(Data); + uint8_t Type = mergeTypeForSet(MCELF::GetType(OrigData), MCELF::GetType(Data)); uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); // Other and Visibility share the same byte with Visibility using the lower diff --git a/llvm/test/MC/ELF/type.s b/llvm/test/MC/ELF/type.s index c2f3631ec43..638d8286991 100644 --- a/llvm/test/MC/ELF/type.s +++ b/llvm/test/MC/ELF/type.s @@ -41,6 +41,95 @@ tls_upper_case: .global tls_upper_case .type tls_upper_case,STT_TLS +// Test that .set doesnt downgrade the type: +// IFUNC > FUNC > OBJECT > NOTYPE +// TLS_OBJECT > OBJECT > NOTYPE +// also TLS_OBJECT is incompatible with IFUNC and FUNC + + .global sym1 + .type sym1, @gnu_indirect_function +alias1: + .global alias1 + .type alias1, @function + .set sym1, alias1 + + .global sym2 + .type sym2, @gnu_indirect_function +alias2: + .global alias2 + .type alias2, @object + .set sym2, alias2 + + .global sym3 + .type sym3, @gnu_indirect_function +alias3: + .global alias3 + .type alias3, @notype + .set sym3, alias3 + + .global sym4 + .type sym4, @function +alias4: + .global alias4 + .type alias4, @object + .set sym4, alias4 + + .global sym5 + .type sym5, @function +alias5: + .global alias5 + .type alias5, @notype + .set sym5, alias5 + + .global sym6 + .type sym6, @object +alias6: + .global alias6 + .type alias6, @notype + .set sym6, alias6 + + .global sym7 + .type sym7, @gnu_indirect_function +alias7: + .global alias7 + .type alias7, @tls_object + .set sym7, alias7 + + .global sym8 + .type sym8, @function + .global alias8 +alias8: + .type alias8, @tls_object + .set sym8, alias8 + + .global sym9 + .type sym9, @tls_object +alias9: + .global alias9 + .type alias9, @object + .set sym9, alias9 + + .global sym10 + .type sym10, @tls_object +alias10: + .global alias10 + .type alias10, @notype + .set sym10, alias10 + + .global sym11 + .type sym11, @tls_object +alias11: + .global alias11 + .type alias11, @gnu_indirect_function + .set sym11, alias11 + + .global sym12 + .type sym12, @tls_object +alias12: + .global alias12 + .type alias12, @function + .set sym12, alias12 + // CHECK: Symbol { // CHECK: Name: bar // CHECK-NEXT: Value: 0x0 @@ -86,6 +175,114 @@ tls_upper_case: // CHECK-NEXT: Other: 0 // CHECK-NEXT: Section: .text (0x1) // CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym1 (54) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: GNU_IFunc (0xA) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym10 (162) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: TLS (0x6) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym11 (176) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: TLS (0x6) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym12 (190) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: TLS (0x6) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym2 (66) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: GNU_IFunc (0xA) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym3 (78) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: GNU_IFunc (0xA) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym4 (90) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: Function (0x2) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym5 (102) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: Function (0x2) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym6 (114) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: Object (0x1) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym7 (126) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: GNU_IFunc (0xA) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym8 (138) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: Function (0x2) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym9 (150) +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: TLS (0x6) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text (0x1) +// CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: tls // CHECK-NEXT: Value: 0x0 |