Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -304,6 +304,18 @@ template static bool compareOutputSections(OutputSectionBase *A, OutputSectionBase *B) { + // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE + // sections that we would like to make sure appear is a specific order + // to maximize their coverage by a single signed 16-bit offset from the + // TOC base pointer. This will apply only to PPC64 because, while .got + // is a generic section name, the others are PPC64-specific. + static const char *PPC64SpecialNames[] = { + // SHT_PROGBITS: + ".got", ".branch_lt", ".toc", ".toc1", ".opd" + }; + static const char **PPC64SpecialNamesEnd = + PPC64SpecialNames + array_lengthof(PPC64SpecialNames); + typedef typename ELFFile::uintX_t uintX_t; uintX_t AFlags = A->getFlags(); @@ -341,7 +353,33 @@ // them is a p_memsz that is larger than p_filesz. Seeing that it // zeros the end of the PT_LOAD, so that has to correspond to the // nobits sections. - return A->getType() != SHT_NOBITS && B->getType() == SHT_NOBITS; + if (A->getType() != SHT_NOBITS && B->getType() == SHT_NOBITS) + return true; + + // Check for the special ordering of special PPC64 section names. + auto PPC64NA = + std::find(PPC64SpecialNames, PPC64SpecialNamesEnd, A->getName()); + auto PPC64NB = + std::find(PPC64SpecialNames, PPC64SpecialNamesEnd, B->getName()); + // First, enforce the relative order in the PPC64SpecialNamesEnd array. + if (PPC64NA != PPC64SpecialNamesEnd && + PPC64NB != PPC64SpecialNamesEnd && + PPC64NA < PPC64NB) + return true; + // Second, any of the special PPC64 sections should come after other + // sections of the same type. + else if (PPC64NB != PPC64SpecialNames && /* not .got */ + PPC64NB != PPC64SpecialNamesEnd && + PPC64NA == PPC64SpecialNamesEnd) + return true; + + // Conversely, the special .tocbss section should be first among all + // SHT_NOBITS sections. This will put it next to the loaded special + // PPC64 sections (and, thus, within reach of the TOC base pointer). + if (A->getName() == ".tocbss") + return true; + + return false; } // Until this function is called, common symbols do not belong to any section. Index: test/elf2/basic64be.s =================================================================== --- test/elf2/basic64be.s +++ test/elf2/basic64be.s @@ -9,6 +9,14 @@ _start: .quad .Lfoo,.TOC.@tocbase,0 +# generate .toc and .toc1 sections to make sure that the ordering is as +# intended (.toc before .toc1, and both before .opd). +.section ".toc1","aw" +.quad 22, 37, 89, 47 + +.section ".toc","aw" +.quad 45, 86, 72, 24 + .text .Lfoo: li 0,1 @@ -28,17 +36,17 @@ # CHECK-NEXT: Type: Executable (0x2) # CHECK-NEXT: Machine: EM_PPC64 (0x15) # CHECK-NEXT: Version: 1 -# CHECK-NEXT: Entry: 0x10020000 +# CHECK-NEXT: Entry: 0x10020040 # CHECK-NEXT: ProgramHeaderOffset: 0x40 -# CHECK-NEXT: SectionHeaderOffset: 0x20078 +# CHECK-NEXT: SectionHeaderOffset: 0x200C8 # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: HeaderSize: 64 # CHECK-NEXT: ProgramHeaderEntrySize: 56 # CHECK-NEXT: ProgramHeaderCount: 3 # CHECK-NEXT: SectionHeaderEntrySize: 64 -# CHECK-NEXT: SectionHeaderCount: 7 -# CHECK-NEXT: StringTableSectionIndex: 6 +# CHECK-NEXT: SectionHeaderCount: 9 +# CHECK-NEXT: StringTableSectionIndex: 8 # CHECK-NEXT: } # CHECK-NEXT: Sections [ # CHECK-NEXT: Section { @@ -55,18 +63,18 @@ # CHECK-NEXT: AddressAlignment: 0 # CHECK-NEXT: EntrySize: 0 # CHECK-NEXT: SectionData ( -# CHECK: ) +# CHECK-NEXT: ) # CHECK-NEXT: } # CHECK-NEXT: Section { # CHECK-NEXT: Index: 1 -# CHECK-NEXT: Name: .text +# CHECK-NEXT: Name: .text (1) # CHECK-NEXT: Type: SHT_PROGBITS (0x1) # CHECK-NEXT: Flags [ (0x6) # CHECK-NEXT: SHF_ALLOC (0x2) # CHECK-NEXT: SHF_EXECINSTR (0x4) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x10010000 -# CHECK-NEXT: Offset: 0x1000 +# CHECK-NEXT: Offset: 0x10000 # CHECK-NEXT: Size: 12 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -77,7 +85,7 @@ # CHECK-NEXT: } # CHECK-NEXT: Section { # CHECK-NEXT: Index: 2 -# CHECK-NEXT: Name: .data +# CHECK-NEXT: Name: .data (45) # CHECK-NEXT: Type: SHT_PROGBITS (0x1) # CHECK-NEXT: Flags [ (0x3) # CHECK-NEXT: SHF_ALLOC (0x2) @@ -95,34 +103,74 @@ # CHECK-NEXT: } # CHECK-NEXT: Section { # CHECK-NEXT: Index: 3 -# CHECK-NEXT: Name: .opd +# CHECK-NEXT: Name: .toc (24) # CHECK-NEXT: Type: SHT_PROGBITS (0x1) # CHECK-NEXT: Flags [ (0x3) # CHECK-NEXT: SHF_ALLOC (0x2) # CHECK-NEXT: SHF_WRITE (0x1) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x10020000 -# CHECK-NEXT: Offset: 0x2000 -# CHECK-NEXT: Size: 24 +# CHECK-NEXT: Offset: 0x20000 +# CHECK-NEXT: Size: 32 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 # CHECK-NEXT: AddressAlignment: 1 # CHECK-NEXT: EntrySize: 0 # CHECK-NEXT: SectionData ( -# CHECK-NEXT: 0000: 00000000 10010000 00000000 00000000 |................| -# CHECK-NEXT: 0010: 00000000 00000000 |........| +# CHECK-NEXT: 0000: 00000000 0000002D 00000000 00000056 |.......-.......V| +# CHECK-NEXT: 0010: 00000000 00000048 00000000 00000018 |.......H........| # CHECK-NEXT: ) # CHECK-NEXT: } # CHECK-NEXT: Section { # CHECK-NEXT: Index: 4 -# CHECK-NEXT: Name: .bss +# CHECK-NEXT: Name: .toc1 (51) +# CHECK-NEXT: Type: SHT_PROGBITS (0x1) +# CHECK-NEXT: Flags [ (0x3) +# CHECK-NEXT: SHF_ALLOC (0x2) +# CHECK-NEXT: SHF_WRITE (0x1) +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x10020020 +# CHECK-NEXT: Offset: 0x20020 +# CHECK-NEXT: Size: 32 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: 00000000 00000016 00000000 00000025 |...............%| +# CHECK-NEXT: 0010: 00000000 00000059 00000000 0000002F |.......Y......./| +# CHECK-NEXT: ) +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 5 +# CHECK-NEXT: Name: .opd (19) +# CHECK-NEXT: Type: SHT_PROGBITS (0x1) +# CHECK-NEXT: Flags [ (0x3) +# CHECK-NEXT: SHF_ALLOC (0x2) +# CHECK-NEXT: SHF_WRITE (0x1) +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x10020040 +# CHECK-NEXT: Offset: 0x20040 +# CHECK-NEXT: Size: 24 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: 00000000 10010000 00000000 00000000 |................| +# CHECK-NEXT: 0010: 00000000 00000000 |........| +# CHECK-NEXT: ) +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 6 +# CHECK-NEXT: Name: .bss (14) # CHECK-NEXT: Type: SHT_NOBITS (0x8) # CHECK-NEXT: Flags [ (0x3) # CHECK-NEXT: SHF_ALLOC (0x2) # CHECK-NEXT: SHF_WRITE (0x1) # CHECK-NEXT: ] -# CHECK-NEXT: Address: 0x10020018 -# CHECK-NEXT: Offset: 0x20018 +# CHECK-NEXT: Address: 0x10020058 +# CHECK-NEXT: Offset: 0x20058 # CHECK-NEXT: Size: 0 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -130,15 +178,15 @@ # CHECK-NEXT: EntrySize: 0 # CHECK-NEXT: } # CHECK-NEXT: Section { -# CHECK-NEXT: Index: 5 -# CHECK-NEXT: Name: .symtab -# CHECK-NEXT: Type: SHT_SYMTAB -# CHECK-NEXT: Flags [ +# CHECK-NEXT: Index: 7 +# CHECK-NEXT: Name: .symtab (37) +# CHECK-NEXT: Type: SHT_SYMTAB (0x2) +# CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x20018 +# CHECK-NEXT: Offset: 0x20058 # CHECK-NEXT: Size: 48 -# CHECK-NEXT: Link: 6 +# CHECK-NEXT: Link: 8 # CHECK-NEXT: Info: 1 # CHECK-NEXT: AddressAlignment: 8 # CHECK-NEXT: EntrySize: 24 @@ -146,14 +194,14 @@ # CHECK: ) # CHECK-NEXT: } # CHECK-NEXT: Section { -# CHECK-NEXT: Index: 6 -# CHECK-NEXT: Name: .strtab +# CHECK-NEXT: Index: 8 +# CHECK-NEXT: Name: .strtab (29) # CHECK-NEXT: Type: SHT_STRTAB (0x3) # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x20048 -# CHECK-NEXT: Size: 46 +# CHECK-NEXT: Offset: 0x20088 +# CHECK-NEXT: Size: 57 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 # CHECK-NEXT: AddressAlignment: 1 @@ -163,42 +211,43 @@ # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT: ProgramHeaders [ -# CHECK-NEXT: ProgramHeader { -# CHECK-NEXT: Type: PT_LOAD (0x1) -# CHECK-NEXT: Offset: 0x0 -# CHECK-NEXT: VirtualAddress: 0x10000000 -# CHECK-NEXT: PhysicalAddress: 0x10000000 -# CHECK-NEXT: FileSize: 232 -# CHECK-NEXT: MemSize: 232 -# CHECK-NEXT: Flags [ -# CHECK-NEXT: PF_R -# CHECK-NEXT: ] -# CHECK-NEXT: Alignment: 65536 -# CHECK-NEXT: } -# CHECK-NEXT: ProgramHeader { -# CHECK-NEXT: Type: PT_LOAD (0x1) -# CHECK-NEXT: Offset: 0x1000 -# CHECK-NEXT: VirtualAddress: 0x10010000 -# CHECK-NEXT: PhysicalAddress: 0x10010000 -# CHECK-NEXT: FileSize: 12 -# CHECK-NEXT: MemSize: 12 -# CHECK-NEXT: Flags [ (0x5) -# CHECK-NEXT: PF_R (0x4) -# CHECK-NEXT: PF_X (0x1) -# CHECK-NEXT: ] -# CHECK-NEXT: Alignment: 65536 -# CHECK-NEXT: } -# CHECK-NEXT: ProgramHeader { -# CHECK-NEXT: Type: PT_LOAD (0x1) -# CHECK-NEXT: Offset: 0x2000 -# CHECK-NEXT: VirtualAddress: 0x10020000 -# CHECK-NEXT: PhysicalAddress: 0x10020000 -# CHECK-NEXT: FileSize: 24 -# CHECK-NEXT: MemSize: 24 -# CHECK-NEXT: Flags [ (0x6) -# CHECK-NEXT: PF_R (0x4) -# CHECK-NEXT: PF_W (0x2) -# CHECK-NEXT: ] -# CHECK-NEXT: Alignment: 65536 -# CHECK-NEXT: } -# CHECK-NEXT:] +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD (0x1) +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: VirtualAddress: 0x10000000 +# CHECK-NEXT: PhysicalAddress: 0x10000000 +# CHECK-NEXT: FileSize: 232 +# CHECK-NEXT: MemSize: 232 +# CHECK-NEXT: Flags [ (0x4) +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 65536 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD (0x1) +# CHECK-NEXT: Offset: 0x10000 +# CHECK-NEXT: VirtualAddress: 0x10010000 +# CHECK-NEXT: PhysicalAddress: 0x10010000 +# CHECK-NEXT: FileSize: 12 +# CHECK-NEXT: MemSize: 12 +# CHECK-NEXT: Flags [ (0x5) +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: PF_X (0x1) +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 65536 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD (0x1) +# CHECK-NEXT: Offset: 0x20000 +# CHECK-NEXT: VirtualAddress: 0x10020000 +# CHECK-NEXT: PhysicalAddress: 0x10020000 +# CHECK-NEXT: FileSize: 88 +# CHECK-NEXT: MemSize: 88 +# CHECK-NEXT: Flags [ (0x6) +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: PF_W (0x2) +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 65536 +# CHECK-NEXT: } +# CHECK-NEXT: ] +