forked from OSchip/llvm-project
				
			ELF: Drop the Chunk base class.
With OutputSection being a virtual interface, each concrete OutputSection handles only one type of chunk and we don't need a base Chunk class. So for we have a class that handles input sections and one that handles the string table, but this extends naturally for other outputs (symbol table, merging of SHF_MERGE sections, etc.). llvm-svn: 244972
This commit is contained in:
		
							parent
							
								
									210ea0b31a
								
							
						
					
					
						commit
						83b0dc6392
					
				| 
						 | 
					@ -19,51 +19,38 @@ namespace elf2 {
 | 
				
			||||||
class Defined;
 | 
					class Defined;
 | 
				
			||||||
template <class ELFT> class ObjectFile;
 | 
					template <class ELFT> class ObjectFile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A Chunk represents a chunk of data that will occupy space in the
 | 
					 | 
				
			||||||
// output (if the resolver chose that). It may or may not be backed by
 | 
					 | 
				
			||||||
// a section of an input file. It could be linker-created data, or
 | 
					 | 
				
			||||||
// doesn't even have actual data (if common or bss).
 | 
					 | 
				
			||||||
class Chunk {
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
  virtual ~Chunk() = default;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Returns the size of this chunk (even if this is a common or BSS.)
 | 
					 | 
				
			||||||
  virtual size_t getSize() const = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Write this chunk to a mmap'ed file, assuming Buf is pointing to
 | 
					 | 
				
			||||||
  // beginning of the file. Because this function may use VA values
 | 
					 | 
				
			||||||
  // of other chunks for relocations, you need to set them properly
 | 
					 | 
				
			||||||
  // before calling this function.
 | 
					 | 
				
			||||||
  virtual void writeTo(uint8_t *Buf) = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // The writer sets and uses the addresses.
 | 
					 | 
				
			||||||
  uint64_t getOutputSectionOff() { return OutputSectionOff; }
 | 
					 | 
				
			||||||
  uint32_t getAlign() { return Align; }
 | 
					 | 
				
			||||||
  void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
protected:
 | 
					 | 
				
			||||||
  // The offset from beginning of the output sections this chunk was assigned
 | 
					 | 
				
			||||||
  // to. The writer sets a value.
 | 
					 | 
				
			||||||
  uint64_t OutputSectionOff = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // The alignment of this chunk. The writer uses the value.
 | 
					 | 
				
			||||||
  uint32_t Align = 1;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A chunk corresponding a section of an input file.
 | 
					// A chunk corresponding a section of an input file.
 | 
				
			||||||
template <class ELFT> class SectionChunk : public Chunk {
 | 
					template <class ELFT> class SectionChunk {
 | 
				
			||||||
  typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
 | 
					  typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
 | 
				
			||||||
  typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
 | 
					  typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
 | 
				
			||||||
  typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
 | 
					  typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  SectionChunk(llvm::object::ELFFile<ELFT> *Obj, const Elf_Shdr *Header);
 | 
					  SectionChunk(llvm::object::ELFFile<ELFT> *Obj, const Elf_Shdr *Header);
 | 
				
			||||||
  size_t getSize() const override { return Header->sh_size; }
 | 
					
 | 
				
			||||||
  void writeTo(uint8_t *Buf) override;
 | 
					  // Returns the size of this chunk (even if this is a common or BSS.)
 | 
				
			||||||
 | 
					  size_t getSize() const { return Header->sh_size; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Write this chunk to a mmap'ed file, assuming Buf is pointing to
 | 
				
			||||||
 | 
					  // beginning of the output section.
 | 
				
			||||||
 | 
					  void writeTo(uint8_t *Buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  StringRef getSectionName() const;
 | 
					  StringRef getSectionName() const;
 | 
				
			||||||
  const Elf_Shdr *getSectionHdr() const { return Header; }
 | 
					  const Elf_Shdr *getSectionHdr() const { return Header; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // The writer sets and uses the addresses.
 | 
				
			||||||
 | 
					  uint64_t getOutputSectionOff() { return OutputSectionOff; }
 | 
				
			||||||
 | 
					  uint32_t getAlign() { return Align; }
 | 
				
			||||||
 | 
					  void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
					  // The offset from beginning of the output sections this chunk was assigned
 | 
				
			||||||
 | 
					  // to. The writer sets a value.
 | 
				
			||||||
 | 
					  uint64_t OutputSectionOff = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // The alignment of this chunk. The writer uses the value.
 | 
				
			||||||
 | 
					  uint32_t Align = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // A file this chunk was created from.
 | 
					  // A file this chunk was created from.
 | 
				
			||||||
  llvm::object::ELFFile<ELFT> *Obj;
 | 
					  llvm::object::ELFFile<ELFT> *Obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,18 +66,18 @@ protected:
 | 
				
			||||||
  ~OutputSectionBase() = default;
 | 
					  ~OutputSectionBase() = default;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <bool Is64Bits>
 | 
					template <class ELFT>
 | 
				
			||||||
class OutputSection final : public OutputSectionBase<Is64Bits> {
 | 
					class OutputSection final : public OutputSectionBase<ELFT::Is64Bits> {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
 | 
					  typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
 | 
				
			||||||
  OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags)
 | 
					  OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags)
 | 
				
			||||||
      : OutputSectionBase<Is64Bits>(Name, sh_type, sh_flags) {}
 | 
					      : OutputSectionBase<ELFT::Is64Bits>(Name, sh_type, sh_flags) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void addChunk(Chunk *C);
 | 
					  void addChunk(SectionChunk<ELFT> *C);
 | 
				
			||||||
  void writeTo(uint8_t *Buf) override;
 | 
					  void writeTo(uint8_t *Buf) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  std::vector<Chunk *> Chunks;
 | 
					  std::vector<SectionChunk<ELFT> *> Chunks;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <bool Is64Bits>
 | 
					template <bool Is64Bits>
 | 
				
			||||||
| 
						 | 
					@ -117,7 +117,7 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SymbolTable *Symtab;
 | 
					  SymbolTable *Symtab;
 | 
				
			||||||
  std::unique_ptr<llvm::FileOutputBuffer> Buffer;
 | 
					  std::unique_ptr<llvm::FileOutputBuffer> Buffer;
 | 
				
			||||||
  llvm::SpecificBumpPtrAllocator<OutputSection<ELFT::Is64Bits>> CAlloc;
 | 
					  llvm::SpecificBumpPtrAllocator<OutputSection<ELFT>> CAlloc;
 | 
				
			||||||
  std::vector<OutputSectionBase<ELFT::Is64Bits> *> OutputSections;
 | 
					  std::vector<OutputSectionBase<ELFT::Is64Bits> *> OutputSections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uintX_t FileSize;
 | 
					  uintX_t FileSize;
 | 
				
			||||||
| 
						 | 
					@ -155,7 +155,8 @@ template <class ELFT> void Writer<ELFT>::run() {
 | 
				
			||||||
  error(Buffer->commit());
 | 
					  error(Buffer->commit());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <bool Is64Bits> void OutputSection<Is64Bits>::addChunk(Chunk *C) {
 | 
					template <class ELFT>
 | 
				
			||||||
 | 
					void OutputSection<ELFT>::addChunk(SectionChunk<ELFT> *C) {
 | 
				
			||||||
  Chunks.push_back(C);
 | 
					  Chunks.push_back(C);
 | 
				
			||||||
  uint32_t Align = C->getAlign();
 | 
					  uint32_t Align = C->getAlign();
 | 
				
			||||||
  if (Align > this->Header.sh_addralign)
 | 
					  if (Align > this->Header.sh_addralign)
 | 
				
			||||||
| 
						 | 
					@ -168,8 +169,8 @@ template <bool Is64Bits> void OutputSection<Is64Bits>::addChunk(Chunk *C) {
 | 
				
			||||||
  this->Header.sh_size = Off;
 | 
					  this->Header.sh_size = Off;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <bool Is64Bits> void OutputSection<Is64Bits>::writeTo(uint8_t *Buf) {
 | 
					template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
 | 
				
			||||||
  for (Chunk *C : Chunks)
 | 
					  for (SectionChunk<ELFT> *C : Chunks)
 | 
				
			||||||
    C->writeTo(Buf);
 | 
					    C->writeTo(Buf);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -225,18 +226,17 @@ template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create output section objects and add them to OutputSections.
 | 
					// Create output section objects and add them to OutputSections.
 | 
				
			||||||
template <class ELFT> void Writer<ELFT>::createSections() {
 | 
					template <class ELFT> void Writer<ELFT>::createSections() {
 | 
				
			||||||
  SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSection<ELFT::Is64Bits> *>
 | 
					  SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSection<ELFT> *> Map;
 | 
				
			||||||
      Map;
 | 
					 | 
				
			||||||
  for (std::unique_ptr<ObjectFileBase> &FileB : Symtab->ObjectFiles) {
 | 
					  for (std::unique_ptr<ObjectFileBase> &FileB : Symtab->ObjectFiles) {
 | 
				
			||||||
    auto &File = cast<ObjectFile<ELFT>>(*FileB);
 | 
					    auto &File = cast<ObjectFile<ELFT>>(*FileB);
 | 
				
			||||||
    for (SectionChunk<ELFT> *C : File.getChunks()) {
 | 
					    for (SectionChunk<ELFT> *C : File.getChunks()) {
 | 
				
			||||||
      const Elf_Shdr *H = C->getSectionHdr();
 | 
					      const Elf_Shdr *H = C->getSectionHdr();
 | 
				
			||||||
      SectionKey<ELFT::Is64Bits> Key{C->getSectionName(), H->sh_type,
 | 
					      SectionKey<ELFT::Is64Bits> Key{C->getSectionName(), H->sh_type,
 | 
				
			||||||
                                     H->sh_flags};
 | 
					                                     H->sh_flags};
 | 
				
			||||||
      OutputSection<ELFT::Is64Bits> *&Sec = Map[Key];
 | 
					      OutputSection<ELFT> *&Sec = Map[Key];
 | 
				
			||||||
      if (!Sec) {
 | 
					      if (!Sec) {
 | 
				
			||||||
        Sec = new (CAlloc.Allocate())
 | 
					        Sec = new (CAlloc.Allocate())
 | 
				
			||||||
            OutputSection<ELFT::Is64Bits>(Key.Name, Key.sh_type, Key.sh_flags);
 | 
					            OutputSection<ELFT>(Key.Name, Key.sh_type, Key.sh_flags);
 | 
				
			||||||
        OutputSections.push_back(Sec);
 | 
					        OutputSections.push_back(Sec);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      Sec->addChunk(C);
 | 
					      Sec->addChunk(C);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue