Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -308,6 +308,63 @@ Script->writeDataBytes(Name, Buf); } +// TODO: the following function is almost identical with llvm-readobj and +// should probably be shared +#define LLD_STRINGIFY_ENUM_CASE(flag) case flag: return #flag + +static std::string getElfSectionType(unsigned Type) { + switch (Config->EMachine) { + case ELF::EM_ARM: + switch (Type) { + LLD_STRINGIFY_ENUM_CASE(SHT_ARM_EXIDX); + LLD_STRINGIFY_ENUM_CASE(SHT_ARM_PREEMPTMAP); + LLD_STRINGIFY_ENUM_CASE(SHT_ARM_ATTRIBUTES); + LLD_STRINGIFY_ENUM_CASE(SHT_ARM_DEBUGOVERLAY); + LLD_STRINGIFY_ENUM_CASE(SHT_ARM_OVERLAYSECTION); + } + case ELF::EM_HEXAGON: + switch (Type) { LLD_STRINGIFY_ENUM_CASE(SHT_HEX_ORDERED); } + case ELF::EM_X86_64: + switch (Type) { LLD_STRINGIFY_ENUM_CASE(SHT_X86_64_UNWIND); } + case ELF::EM_MIPS: + case ELF::EM_MIPS_RS3_LE: + switch (Type) { + LLD_STRINGIFY_ENUM_CASE(SHT_MIPS_REGINFO); + LLD_STRINGIFY_ENUM_CASE(SHT_MIPS_OPTIONS); + LLD_STRINGIFY_ENUM_CASE(SHT_MIPS_ABIFLAGS); + LLD_STRINGIFY_ENUM_CASE(SHT_MIPS_DWARF); + } + } + + switch (Type) { + LLD_STRINGIFY_ENUM_CASE(SHT_NULL ); + LLD_STRINGIFY_ENUM_CASE(SHT_PROGBITS ); + LLD_STRINGIFY_ENUM_CASE(SHT_SYMTAB ); + LLD_STRINGIFY_ENUM_CASE(SHT_STRTAB ); + LLD_STRINGIFY_ENUM_CASE(SHT_RELA ); + LLD_STRINGIFY_ENUM_CASE(SHT_HASH ); + LLD_STRINGIFY_ENUM_CASE(SHT_DYNAMIC ); + LLD_STRINGIFY_ENUM_CASE(SHT_NOTE ); + LLD_STRINGIFY_ENUM_CASE(SHT_NOBITS ); + LLD_STRINGIFY_ENUM_CASE(SHT_REL ); + LLD_STRINGIFY_ENUM_CASE(SHT_SHLIB ); + LLD_STRINGIFY_ENUM_CASE(SHT_DYNSYM ); + LLD_STRINGIFY_ENUM_CASE(SHT_INIT_ARRAY ); + LLD_STRINGIFY_ENUM_CASE(SHT_FINI_ARRAY ); + LLD_STRINGIFY_ENUM_CASE(SHT_PREINIT_ARRAY ); + LLD_STRINGIFY_ENUM_CASE(SHT_GROUP ); + LLD_STRINGIFY_ENUM_CASE(SHT_SYMTAB_SHNDX ); + LLD_STRINGIFY_ENUM_CASE(SHT_GNU_ATTRIBUTES ); + LLD_STRINGIFY_ENUM_CASE(SHT_GNU_HASH ); + LLD_STRINGIFY_ENUM_CASE(SHT_GNU_verdef ); + LLD_STRINGIFY_ENUM_CASE(SHT_GNU_verneed ); + LLD_STRINGIFY_ENUM_CASE(SHT_GNU_versym ); + default: + return "0x" + utohexstr(Type); + } +} +#undef LLD_STRINGIFY_ENUM_CASE + static uint64_t getOutFlags(InputSectionBase *S) { return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED; } @@ -411,8 +468,11 @@ 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 " + IS->Name + " has different type (" + + getElfSectionType(IS->Type) + ") from output section " + + Sec->Name + " (" + getElfSectionType(Sec->Type) + + ")\n>>> input section " + IS->Name + " is defined in " + + toString(IS->File)); } 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,9 @@ // 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 .shstrtab has different type (SHT_STRTAB) from output section .shstrtab (SHT_PROGBITS) +// CHECK-NEXT: >>> input section .shstrtab is defined in (internal) + .section .shstrtab,"" .short 20