[PECOFF][Writer] Fixed a bug that an empty section is emit to the section header.

llvm-svn: 186066
This commit is contained in:
Rui Ueyama 2013-07-11 05:43:38 +00:00
parent 37039640e3
commit a3635b7b3b
2 changed files with 34 additions and 36 deletions

View File

@ -400,15 +400,11 @@ public:
static bool classof(const Chunk *c) { return c->getKind() == kindSection; } static bool classof(const Chunk *c) { return c->getKind() == kindSection; }
protected: protected:
SectionChunk(SectionHeaderTableChunk *table, StringRef sectionName, SectionChunk(StringRef sectionName, uint32_t characteristics)
uint32_t characteristics)
: AtomChunk(kindSection), : AtomChunk(kindSection),
_sectionHeader(createSectionHeader(sectionName, characteristics)) { _sectionHeader(createSectionHeader(sectionName, characteristics)) {
// The section should be aligned to disk sector. // The section should be aligned to disk sector.
_align = SECTOR_SIZE; _align = SECTOR_SIZE;
// Add this section to the file header.
table->addSection(this);
} }
void buildContents(const File &linkedFile, void buildContents(const File &linkedFile,
@ -478,11 +474,6 @@ void SectionHeaderTableChunk::write(uint8_t *fileBuffer) {
uint64_t offset = 0; uint64_t offset = 0;
fileBuffer += fileOffset(); fileBuffer += fileOffset();
for (const auto &chunk : _sections) { for (const auto &chunk : _sections) {
// Skip the empty section. Windows loader does not like a section
// of size zero and rejects such executable.
if (chunk->size() == 0)
continue;
const llvm::object::coff_section &header = chunk->getSectionHeader(); const llvm::object::coff_section &header = chunk->getSectionHeader();
std::memcpy(fileBuffer + offset, &header, sizeof(header)); std::memcpy(fileBuffer + offset, &header, sizeof(header));
offset += sizeof(header); offset += sizeof(header);
@ -492,8 +483,8 @@ void SectionHeaderTableChunk::write(uint8_t *fileBuffer) {
// \brief A TextSectionChunk represents a .text section. // \brief A TextSectionChunk represents a .text section.
class TextSectionChunk : public SectionChunk { class TextSectionChunk : public SectionChunk {
public: public:
TextSectionChunk(const File &linkedFile, SectionHeaderTableChunk *table) TextSectionChunk(const File &linkedFile)
: SectionChunk(table, ".text", characteristics) { : SectionChunk(".text", characteristics) {
buildContents(linkedFile, [](const DefinedAtom *atom) { buildContents(linkedFile, [](const DefinedAtom *atom) {
return atom->contentType() == DefinedAtom::typeCode; return atom->contentType() == DefinedAtom::typeCode;
}); });
@ -509,8 +500,8 @@ private:
// \brief A RDataSectionChunk represents a .rdata section. // \brief A RDataSectionChunk represents a .rdata section.
class RDataSectionChunk : public SectionChunk { class RDataSectionChunk : public SectionChunk {
public: public:
RDataSectionChunk(const File &linkedFile, SectionHeaderTableChunk *table) RDataSectionChunk(const File &linkedFile)
: SectionChunk(table, ".rdata", characteristics) { : SectionChunk(".rdata", characteristics) {
buildContents(linkedFile, [](const DefinedAtom *atom) { buildContents(linkedFile, [](const DefinedAtom *atom) {
return (atom->contentType() == DefinedAtom::typeData && return (atom->contentType() == DefinedAtom::typeData &&
atom->permissions() == DefinedAtom::permR__); atom->permissions() == DefinedAtom::permR__);
@ -527,8 +518,8 @@ private:
// \brief A DataSectionChunk represents a .data section. // \brief A DataSectionChunk represents a .data section.
class DataSectionChunk : public SectionChunk { class DataSectionChunk : public SectionChunk {
public: public:
DataSectionChunk(const File &linkedFile, SectionHeaderTableChunk *table) DataSectionChunk(const File &linkedFile)
: SectionChunk(table, ".data", characteristics) { : SectionChunk(".data", characteristics) {
buildContents(linkedFile, [](const DefinedAtom *atom) { buildContents(linkedFile, [](const DefinedAtom *atom) {
return (atom->contentType() == DefinedAtom::typeData && return (atom->contentType() == DefinedAtom::typeData &&
atom->permissions() == DefinedAtom::permRW_); atom->permissions() == DefinedAtom::permRW_);
@ -569,20 +560,21 @@ private:
chunk->align()); chunk->align());
chunk->setFileOffset(_imageSizeOnDisk); chunk->setFileOffset(_imageSizeOnDisk);
_imageSizeOnDisk += chunk->size(); _imageSizeOnDisk += chunk->size();
}
// Compute and set the starting address of sections when loaded in void maybeAddSectionChunk(SectionChunk *chunk,
// memory. They are different from positions on disk because sections need SectionHeaderTableChunk *table) {
// to be sector-aligned on disk but page-aligned in memory. // Skip the empty section. Windows loader does not like a section of size
if (SectionChunk *sectionChunk = dyn_cast<SectionChunk>(chunk)) { // zero and rejects such executable.
sectionChunk->setVirtualAddress(_imageSizeInMemory);
// Skip the empty section.
if (chunk->size() == 0) if (chunk->size() == 0)
return; return;
addChunk(chunk);
table->addSection(chunk);
_numSections++; _numSections++;
chunk->setVirtualAddress(_imageSizeInMemory);
_imageSizeInMemory = llvm::RoundUpToAlignment( _imageSizeInMemory = llvm::RoundUpToAlignment(
_imageSizeInMemory + chunk->size(), PAGE_SIZE); _imageSizeInMemory + chunk->size(), PAGE_SIZE);
} }
}
public: public:
explicit ExecutableWriter(const PECOFFTargetInfo &targetInfo) explicit ExecutableWriter(const PECOFFTargetInfo &targetInfo)
@ -596,23 +588,29 @@ public:
auto *peHeader = new PEHeaderChunk(_PECOFFTargetInfo); auto *peHeader = new PEHeaderChunk(_PECOFFTargetInfo);
auto *dataDirectory = new DataDirectoryChunk(); auto *dataDirectory = new DataDirectoryChunk();
auto *sectionTable = new SectionHeaderTableChunk(); auto *sectionTable = new SectionHeaderTableChunk();
auto *text = new TextSectionChunk(linkedFile, sectionTable); auto *text = new TextSectionChunk(linkedFile);
auto *rdata = new RDataSectionChunk(linkedFile, sectionTable); auto *rdata = new RDataSectionChunk(linkedFile);
auto *data = new DataSectionChunk(linkedFile, sectionTable); auto *data = new DataSectionChunk(linkedFile);
addChunk(dosStub); addChunk(dosStub);
addChunk(peHeader); addChunk(peHeader);
addChunk(dataDirectory); addChunk(dataDirectory);
addChunk(sectionTable); addChunk(sectionTable);
addChunk(text); maybeAddSectionChunk(text, sectionTable);
addChunk(rdata); maybeAddSectionChunk(rdata, sectionTable);
addChunk(data); maybeAddSectionChunk(data, sectionTable);
// Now that we know the size and file offset of sections. Set the file // Now that we know the size and file offset of sections. Set the file
// header accordingly. // header accordingly.
peHeader->setSizeOfCode(text->size()); peHeader->setSizeOfCode(text->size());
if (text->size() > 0) {
peHeader->setBaseOfCode(text->getVirtualAddress()); peHeader->setBaseOfCode(text->getVirtualAddress());
}
if (rdata->size() > 0) {
peHeader->setBaseOfData(rdata->getVirtualAddress()); peHeader->setBaseOfData(rdata->getVirtualAddress());
} else if (data->size() > 0) {
peHeader->setBaseOfData(data->getVirtualAddress());
}
peHeader->setSizeOfInitializedData(rdata->size() + data->size()); peHeader->setSizeOfInitializedData(rdata->size() + data->size());
peHeader->setNumberOfSections(_numSections); peHeader->setNumberOfSections(_numSections);
peHeader->setSizeOfImage(_imageSizeInMemory); peHeader->setSizeOfImage(_imageSizeInMemory);

View File

@ -34,7 +34,7 @@ FILE: SizeOfInitializedData: 0
FILE: SizeOfUninitializedData: 0 FILE: SizeOfUninitializedData: 0
FILE: AddressOfEntryPoint: 0x1000 FILE: AddressOfEntryPoint: 0x1000
FILE: BaseOfCode: 0x1000 FILE: BaseOfCode: 0x1000
FILE: BaseOfData: 0x2000 FILE: BaseOfData: 0
FILE: ImageBase: 0x400000 FILE: ImageBase: 0x400000
FILE: SectionAlignment: 4096 FILE: SectionAlignment: 4096
FILE: FileAlignment: 512 FILE: FileAlignment: 512