[PECOFF] Refactor COFF section header creation.

Code to create COFF section header was scattered across many member functions
of SectionChunk. Consolidate it to a member function of SectionHeaderTableChunk.

llvm-svn: 196895
This commit is contained in:
Rui Ueyama 2013-12-10 08:39:06 +00:00
parent 89a346c2a1
commit d9d4be6993
1 changed files with 46 additions and 75 deletions

View File

@ -174,6 +174,8 @@ public:
virtual void write(uint8_t *fileBuffer);
private:
static llvm::object::coff_section createSectionHeader(SectionChunk *chunk);
std::vector<SectionChunk *> _sections;
};
@ -197,7 +199,7 @@ public:
layout->_fileOffset += fileOffset;
}
uint64_t getSectionRva() {
uint64_t getVirtualAddress() {
assert(_atomLayouts.size() > 0);
return _atomLayouts[0]->_virtualAddr;
}
@ -266,22 +268,8 @@ public:
virtual uint64_t rawSize() const { return _size; }
// Set the file offset of the beginning of this section.
virtual void setFileOffset(uint64_t fileOffset) {
AtomChunk::setFileOffset(fileOffset);
_sectionHeader.PointerToRawData = fileOffset;
}
virtual void setVirtualAddress(uint32_t rva) {
_sectionHeader.VirtualAddress = rva;
AtomChunk::setVirtualAddress(rva);
}
uint32_t getVirtualAddress() const { return _sectionHeader.VirtualAddress; }
llvm::object::coff_section &getSectionHeader();
ulittle32_t getSectionCharacteristics() const;
void appendAtom(const DefinedAtom *atom);
uint32_t getCharacteristics() const { return _characteristics; }
StringRef getSectionName() const { return _sectionName; }
static bool classof(const Chunk *c) { return c->getKind() == kindSection; }
@ -291,12 +279,8 @@ protected:
StringRef _sectionName;
const uint32_t _characteristics;
llvm::object::coff_section _sectionHeader;
private:
llvm::object::coff_section
createSectionHeader(StringRef sectionName, uint32_t characteristics) const;
mutable llvm::BumpPtrAllocator _alloc;
};
@ -311,8 +295,6 @@ public:
: SectionChunk(name, getCharacteristics(ctx, name, atoms)) {
for (auto *a : atoms)
appendAtom(a);
_sectionHeader.VirtualSize = _size;
_sectionHeader.SizeOfRawData = size();
}
private:
@ -612,24 +594,6 @@ void DataDirectoryChunk::write(uint8_t *fileBuffer) {
baseReloc->Size = _baseRelocSize;
}
llvm::object::coff_section &SectionChunk::getSectionHeader() {
if (_characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
_sectionHeader.VirtualSize = 0;
_sectionHeader.PointerToRawData = 0;
} else {
// Fix up section size before returning it. VirtualSize should be the size
// of the actual content, and SizeOfRawData should be aligned to the section
// alignment.
_sectionHeader.VirtualSize = _size;
_sectionHeader.SizeOfRawData = size();
}
return _sectionHeader;
}
ulittle32_t SectionChunk::getSectionCharacteristics() const {
return _sectionHeader.Characteristics;
}
void SectionChunk::appendAtom(const DefinedAtom *atom) {
// Atom may have to be at a proper alignment boundary. If so, move the
// pointer to make a room after the last atom before adding new one.
@ -642,41 +606,12 @@ void SectionChunk::appendAtom(const DefinedAtom *atom) {
}
SectionChunk::SectionChunk(StringRef sectionName, uint32_t characteristics)
: AtomChunk(kindSection), _sectionName(sectionName), _characteristics(characteristics),
_sectionHeader(createSectionHeader(sectionName, characteristics)) {
: AtomChunk(kindSection), _sectionName(sectionName),
_characteristics(characteristics) {
// The section should be aligned to disk sector.
_align = SECTOR_SIZE;
}
llvm::object::coff_section
SectionChunk::createSectionHeader(StringRef sectionName,
uint32_t characteristics) const {
llvm::object::coff_section header;
// Section name equal to or shorter than 8 byte fits in the section
// header. Longer names should be stored to string table, which is not
// implemented yet.
if (sizeof(header.Name) < sectionName.size())
llvm_unreachable("Cannot handle section name longer than 8 byte");
// Name field must be NUL-padded. If the name is exactly 8 byte long,
// there's no terminating NUL.
std::memset(header.Name, 0, sizeof(header.Name));
std::strncpy(header.Name, sectionName.data(),
std::min(sizeof(header.Name), sectionName.size()));
header.VirtualSize = 0;
header.VirtualAddress = 0;
header.SizeOfRawData = 0;
header.PointerToRawData = 0;
header.PointerToRelocations = 0;
header.PointerToLinenumbers = 0;
header.NumberOfRelocations = 0;
header.NumberOfLinenumbers = 0;
header.Characteristics = characteristics;
return header;
}
void GenericSectionChunk::write(uint8_t *fileBuffer) {
if (_atomLayouts.empty())
return;
@ -736,13 +671,49 @@ uint64_t SectionHeaderTableChunk::size() const {
void SectionHeaderTableChunk::write(uint8_t *fileBuffer) {
uint64_t offset = 0;
fileBuffer += fileOffset();
for (const auto &chunk : _sections) {
const llvm::object::coff_section &header = chunk->getSectionHeader();
for (SectionChunk *chunk : _sections) {
llvm::object::coff_section header = createSectionHeader(chunk);
std::memcpy(fileBuffer + offset, &header, sizeof(header));
offset += sizeof(header);
}
}
llvm::object::coff_section
SectionHeaderTableChunk::createSectionHeader(SectionChunk *chunk) {
llvm::object::coff_section header;
// Section name equal to or shorter than 8 byte fits in the section
// header. Longer names should be stored to string table, which is not
// implemented yet.
StringRef sectionName = chunk->getSectionName();
if (sizeof(header.Name) < sectionName.size())
llvm_unreachable("Cannot handle section name longer than 8 byte");
// Name field must be NUL-padded. If the name is exactly 8 byte long,
// there's no terminating NUL.
std::memset(header.Name, 0, sizeof(header.Name));
std::strncpy(header.Name, sectionName.data(),
std::min(sizeof(header.Name), sectionName.size()));
uint32_t characteristics = chunk->getCharacteristics();
header.VirtualAddress = chunk->getVirtualAddress();
header.PointerToRelocations = 0;
header.PointerToLinenumbers = 0;
header.NumberOfRelocations = 0;
header.NumberOfLinenumbers = 0;
header.SizeOfRawData = chunk->size();
header.Characteristics = characteristics;
if (characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
header.VirtualSize = 0;
header.PointerToRawData = 0;
} else {
header.VirtualSize = chunk->rawSize();
header.PointerToRawData = chunk->fileOffset();
}
return header;
}
/// Creates .reloc section content from the other sections. The content of
/// .reloc is basically a list of relocation sites. The relocation sites are
/// divided into blocks. Each block represents the base relocation for a 4K
@ -951,7 +922,7 @@ void ExecutableWriter::build(const File &linkedFile) {
baseReloc->setContents(_chunks);
if (baseReloc->size()) {
addSectionChunk(baseReloc, sectionTable);
dataDirectory->setBaseRelocField(baseReloc->getSectionRva(),
dataDirectory->setBaseRelocField(baseReloc->getVirtualAddress(),
baseReloc->rawSize());
}
}
@ -1075,7 +1046,7 @@ uint64_t ExecutableWriter::calcSectionSize(
uint64_t ret = 0;
for (auto &cp : _chunks)
if (SectionChunk *chunk = dyn_cast<SectionChunk>(&*cp))
if (chunk->getSectionCharacteristics() & sectionType)
if (chunk->getCharacteristics() & sectionType)
ret += chunk->size();
return ret;
}