Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -13,6 +13,7 @@ #include "SymbolTable.h" #include "Target.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/FileOutputBuffer.h" using namespace llvm; @@ -300,6 +301,22 @@ } } +// 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. +// 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). +static int getPPC64SectionRank(StringRef SectionName) { + return StringSwitch(SectionName) + .Case(".tocbss", 0) + .Case(".branch_lt", 2) + .Case(".toc", 3) + .Case(".toc1", 4) + .Case(".opd", 5) + .Default(1); +} + // Output section ordering is determined by this function. template static bool compareOutputSections(OutputSectionBase *A, @@ -341,7 +358,10 @@ // 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; + + return getPPC64SectionRank(A->getName()) < getPPC64SectionRank(B->getName()); } // 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: ] +