// SectionChunk is one of the most frequently allocated classes, so it is
// important to keep it as compact as possible. As of this writing, the number
// below is the size of this class on x64 platforms.
-static_assert(sizeof(SectionChunk) <= 104, "SectionChunk grew unexpectedly");
+static_assert(sizeof(SectionChunk) <= 96, "SectionChunk grew unexpectedly");
static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
MergeChunk *MergeChunk::Instances[Log2MaxSectionAlignment + 1] = {};
MergeChunk::MergeChunk(uint32_t Alignment)
- : Builder(StringTableBuilder::RAW, Alignment) {
+ : Chunk(OtherKind), Builder(StringTableBuilder::RAW, Alignment) {
setAlignment(Alignment);
}
if (!C->Live)
continue;
size_t Off = Builder.getOffset(toStringRef(C->getContents()));
- C->setOutputSection(Out);
C->setRVA(RVA + Off);
}
}
// An output section has pointers to chunks in the section, and each
// chunk has a back pointer to an output section.
- void setOutputSection(OutputSection *O) { Out = O; }
- OutputSection *getOutputSection() const { return Out; }
+ void setOutputSectionIdx(uint16_t O) { OSIdx = O; }
+ uint16_t getOutputSectionIdx() const { return OSIdx; }
+ OutputSection *getOutputSection() const;
// Windows-specific.
// Collect all locations that contain absolute addresses for base relocations.
// value.
uint8_t P2Align = 0;
+ // The output section index for this chunk. The first valid section number is
+ // one.
+ uint16_t OSIdx = 0;
+
// The RVA of this chunk in the output. The writer sets a value.
uint32_t RVA = 0;
-
- // The output section for this chunk.
- OutputSection *Out = nullptr;
};
// A chunk corresponding a section of an input file.
static const int NumberOfDataDirectory = 16;
+// Global vector of all output sections. After output sections are finalized,
+// this can be indexed by Chunk::getOutputSection.
+static std::vector<OutputSection *> OutputSections;
+
+OutputSection *Chunk::getOutputSection() const {
+ return OSIdx == 0 ? nullptr : OutputSections[OSIdx - 1];
+}
+
namespace {
class DebugDirectoryChunk : public Chunk {
void assignAddresses();
void finalizeAddresses();
void removeEmptySections();
+ void assignOutputSectionIndices();
void createSymbolAndStringTable();
void openFile(StringRef OutputPath);
template <typename PEHeaderTy> void writeHeader();
std::unique_ptr<FileOutputBuffer> &Buffer;
std::map<PartialSectionKey, PartialSection *> PartialSections;
- std::vector<OutputSection *> OutputSections;
std::vector<char> Strtab;
std::vector<llvm::object::coff_symbol16> OutputSymtab;
IdataContents Idata;
void OutputSection::addChunk(Chunk *C) {
Chunks.push_back(C);
- C->setOutputSection(this);
}
void OutputSection::insertChunkAtStart(Chunk *C) {
Chunks.insert(Chunks.begin(), C);
- C->setOutputSection(this);
}
void OutputSection::setPermissions(uint32_t C) {
}
void OutputSection::merge(OutputSection *Other) {
- for (Chunk *C : Other->Chunks)
- C->setOutputSection(this);
Chunks.insert(Chunks.end(), Other->Chunks.begin(), Other->Chunks.end());
Other->Chunks.clear();
ContribSections.insert(ContribSections.end(), Other->ContribSections.begin(),
Chunk *ThunkChunk = Thunk->getChunk();
ThunkChunk->setRVA(
ThunkInsertionRVA); // Estimate of where it will be located.
- ThunkChunk->setOutputSection(OS);
OS->Chunks.insert(OS->Chunks.begin() + ThunkInsertionSpot, ThunkChunk);
ThunkInsertionSpot++;
ThunksSize += ThunkChunk->getSize();
removeUnusedSections();
finalizeAddresses();
removeEmptySections();
+ assignOutputSectionIndices();
setSectionPermissions();
createSymbolAndStringTable();
OutputSections.erase(
std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty),
OutputSections.end());
+}
+
+void Writer::assignOutputSectionIndices() {
+ // Assign final output section indices, and assign each chunk to its output
+ // section.
uint32_t Idx = 1;
- for (OutputSection *Sec : OutputSections)
- Sec->SectionIndex = Idx++;
+ for (OutputSection *OS : OutputSections) {
+ OS->SectionIndex = Idx;
+ for (Chunk *C : OS->Chunks)
+ C->setOutputSectionIdx(Idx);
+ ++Idx;
+ }
+
+ // Merge chunks are containers of chunks, so assign those an output section
+ // too.
+ for (MergeChunk *MC : MergeChunk::Instances)
+ if (MC)
+ for (SectionChunk *SC : MC->Sections)
+ if (SC && SC->Live)
+ SC->setOutputSectionIdx(MC->getOutputSectionIdx());
}
size_t Writer::addEntryToStringTable(StringRef Str) {
// section.
auto *D = cast<DefinedRegular>(S);
if (D->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
- Chunk *RefChunk = D->getChunk();
- OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr;
- if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE)
+ SectionChunk *SC = dyn_cast<SectionChunk>(D->getChunk());
+ if (SC && SC->Live &&
+ SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)
addSymbolToRVASet(AddressTakenSyms, D);
}
break;
return;
// We assume .pdata contains function table entries only.
auto BufAddr = [&](Chunk *C) {
- return Buffer->getBufferStart() + C->getOutputSection()->getFileOff() +
- C->getRVA() - C->getOutputSection()->getRVA();
+ OutputSection *OS = C->getOutputSection();
+ return Buffer->getBufferStart() + OS->getFileOff() + C->getRVA() -
+ OS->getRVA();
};
uint8_t *Begin = BufAddr(FirstPdata);
uint8_t *End = BufAddr(LastPdata) + LastPdata->getSize();