diff options
-rw-r--r-- | lld/ELF/Writer.cpp | 40 | ||||
-rw-r--r-- | lld/test/elf2/symbols.s | 18 |
2 files changed, 46 insertions, 12 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 94b42656a1c..eea86f27f48 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -60,6 +60,7 @@ public: // Returns the size of the section in the output file. uintX_t getSize() { return Header.sh_size; } + void setSize(uintX_t Val) { Header.sh_size = Val; } uintX_t getFlags() { return Header.sh_flags; } uintX_t getFileOff() { return Header.sh_offset; } uintX_t getAlign() { return Header.sh_addralign; } @@ -149,6 +150,7 @@ template <class ELFT> class Writer { public: typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr; + typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym; Writer(SymbolTable *T) : SymTable(*T), StringTable(T->getStringBuilder()) {} void run(); @@ -397,6 +399,18 @@ template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> { // Create output section objects and add them to OutputSections. template <class ELFT> void Writer<ELFT>::createSections() { SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSection<ELFT> *> Map; + auto getSection = [&](StringRef Name, uint32_t sh_type, + uintX_t sh_flags) -> OutputSection<ELFT> * { + SectionKey<ELFT::Is64Bits> Key{Name, sh_type, sh_flags}; + OutputSection<ELFT> *&Sec = Map[Key]; + if (!Sec) { + Sec = new (CAlloc.Allocate()) + OutputSection<ELFT>(Key.Name, Key.sh_type, Key.sh_flags); + addOutputSection(Sec); + } + return Sec; + }; + const SymbolTable &Symtab = SymTable.getSymTable(); for (const std::unique_ptr<ObjectFileBase> &FileB : Symtab.ObjectFiles) { auto &File = cast<ObjectFile<ELFT>>(*FileB); @@ -404,17 +418,27 @@ template <class ELFT> void Writer<ELFT>::createSections() { if (!C) continue; const Elf_Shdr *H = C->getSectionHdr(); - SectionKey<ELFT::Is64Bits> Key{C->getSectionName(), H->sh_type, - H->sh_flags}; - OutputSection<ELFT> *&Sec = Map[Key]; - if (!Sec) { - Sec = new (CAlloc.Allocate()) - OutputSection<ELFT>(Key.Name, Key.sh_type, Key.sh_flags); - addOutputSection(Sec); - } + OutputSection<ELFT> *Sec = + getSection(C->getSectionName(), H->sh_type, H->sh_flags); Sec->addChunk(C); } } + + OutputSection<ELFT> *BSSSec = + getSection(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); + uintX_t Off = BSSSec->getSize(); + // FIXME: Try to avoid the extra walk over all global symbols. + for (auto &P : Symtab.getSymbols()) { + SymbolBody *Body = P.second->Body; + auto *C = dyn_cast<DefinedCommon<ELFT>>(Body); + if (!C) + continue; + const Elf_Sym &Sym = C->Sym; + uintX_t Align = Sym.st_value; + Off = RoundUpToAlignment(Off, Align); + Off += Sym.st_size; + } + BSSSec->setSize(Off); } template <bool Is64Bits> diff --git a/lld/test/elf2/symbols.s b/lld/test/elf2/symbols.s index 120a21b9a83..ab3c84ded54 100644 --- a/lld/test/elf2/symbols.s +++ b/lld/test/elf2/symbols.s @@ -41,12 +41,22 @@ abs = 0x123 // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x1000 +// CHECK: 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: 0x1004 +// CHECK-NEXT: Offset: 0x1004 +// CHECK-NEXT: Size: 4 + // CHECK: Name: foobar // CHECK-NEXT: Type: SHT_NOBITS // CHECK-NEXT: Flags [ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x1004 +// CHECK-NEXT: Address: 0x1008 // CHECK: Symbols [ // CHECK-NEXT: Symbol { @@ -105,7 +115,7 @@ abs = 0x123 // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: zed -// CHECK-NEXT: Value: 0x1004 +// CHECK-NEXT: Value: 0x1008 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Global (0x1) // CHECK-NEXT: Type: None @@ -114,7 +124,7 @@ abs = 0x123 // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: zed3 -// CHECK-NEXT: Value: 0x100C +// CHECK-NEXT: Value: 0x1010 // CHECK-NEXT: Size: 4 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: None @@ -123,7 +133,7 @@ abs = 0x123 // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: zed2 -// CHECK-NEXT: Value: 0x1008 +// CHECK-NEXT: Value: 0x100C // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: None |