Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -308,6 +308,102 @@ Script->writeDataBytes(Name, Buf); } +// TODO: move this to an LLVM library so it can be shared with llvm-readobj +static std::string getElfSectionType(unsigned Type) { + switch (Config->EMachine) { + case ELF::EM_ARM: + switch (Type) { + case SHT_ARM_EXIDX: + return "SHT_ARM_EXIDX"; + case SHT_ARM_PREEMPTMAP: + return "SHT_ARM_PREEMPTMAP"; + case SHT_ARM_ATTRIBUTES: + return "SHT_ARM_ATTRIBUTES"; + case SHT_ARM_DEBUGOVERLAY: + return "SHT_ARM_DEBUGOVERLAY"; + case SHT_ARM_OVERLAYSECTION: + return "SHT_ARM_OVERLAYSECTION"; + } + break; + case ELF::EM_HEXAGON: + switch (Type) { + case SHT_HEX_ORDERED: + return "SHT_HEX_ORDERED"; + } + break; + case ELF::EM_X86_64: + switch (Type) { + case SHT_X86_64_UNWIND: + return "SHT_X86_64_UNWIND"; + } + break; + case ELF::EM_MIPS: + case ELF::EM_MIPS_RS3_LE: + switch (Type) { + case SHT_MIPS_REGINFO: + return "SHT_MIPS_REGINFO"; + case SHT_MIPS_OPTIONS: + return "SHT_MIPS_OPTIONS"; + case SHT_MIPS_ABIFLAGS: + return "SHT_MIPS_ABIFLAGS"; + case SHT_MIPS_DWARF: + return "SHT_MIPS_DWARF"; + } + break; + default: + break; + } + + switch (Type) { + case SHT_NULL: + return "SHT_NULL"; + case SHT_PROGBITS: + return "SHT_PROGBITS"; + case SHT_SYMTAB: + return "SHT_SYMTAB"; + case SHT_STRTAB: + return "SHT_STRTAB"; + case SHT_RELA: + return "SHT_RELA"; + case SHT_HASH: + return "SHT_HASH"; + case SHT_DYNAMIC: + return "SHT_DYNAMIC"; + case SHT_NOTE: + return "SHT_NOTE"; + case SHT_NOBITS: + return "SHT_NOBITS"; + case SHT_REL: + return "SHT_REL"; + case SHT_SHLIB: + return "SHT_SHLIB"; + case SHT_DYNSYM: + return "SHT_DYNSYM"; + case SHT_INIT_ARRAY: + return "SHT_INIT_ARRAY"; + case SHT_FINI_ARRAY: + return "SHT_FINI_ARRAY"; + case SHT_PREINIT_ARRAY: + return "SHT_PREINIT_ARRAY"; + case SHT_GROUP: + return "SHT_GROUP"; + case SHT_SYMTAB_SHNDX: + return "SHT_SYMTAB_SHNDX"; + case SHT_GNU_ATTRIBUTES: + return "SHT_GNU_ATTRIBUTES"; + case SHT_GNU_HASH: + return "SHT_GNU_HASH"; + case SHT_GNU_verdef: + return "SHT_GNU_verdef"; + case SHT_GNU_verneed: + return "SHT_GNU_verneed"; + case SHT_GNU_versym: + return "SHT_GNU_versym"; + default: + return "0x" + utohexstr(Type); + } +} + static uint64_t getOutFlags(InputSectionBase *S) { return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED; } @@ -411,8 +507,10 @@ if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(IS->Type)) Sec->Type = SHT_PROGBITS; else - error("Section has different type from others with the same name " + - toString(IS)); + error("section type mismatch for " + IS->Name + "\n>>> " + + toString(IS) + ": " + getElfSectionType(IS->Type) + + "\n>>> output section " + Sec->Name + ": " + + getElfSectionType(Sec->Type)); } Sec->Flags |= Flags; } else { Index: test/ELF/incompatible-section-types2.s =================================================================== --- test/ELF/incompatible-section-types2.s +++ test/ELF/incompatible-section-types2.s @@ -1,7 +1,11 @@ // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s -// CHECK: error: Section has different type from others with the same name :(.shstrtab) +// CHECK: error: section type mismatch for .shstrtab +// CHECK-NEXT: >>> :(.shstrtab): SHT_STRTAB +// CHECK-NEXT: >>> output section .shstrtab: SHT_PROGBITS + + .section .shstrtab,"" .short 20