forked from OSchip/llvm-project
[NFC][XCOFF][AIX] Serialize object file writing for each CsectGroup
Summary: Right now we handle each CsectGroup(ProgramCodeCsects, BSSCsects) individually when assigning indices, writing symbol table, and writing section raw data. However, there is already a pattern there, and we could common up those actions for every CsectGroup. This will make adding new CsectGroup(Read Write data, Read only data, TC/TOC, mergeable string) easier, and less error prone. Reviewed by: sfertile, daltenty, DiggerLin Approved by: daltenty Differential Revision: https://reviews.llvm.org/D69112
This commit is contained in:
parent
e5f485c3bd
commit
78207e1f23
|
@ -44,6 +44,7 @@ using namespace llvm;
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr unsigned DefaultSectionAlign = 4;
|
constexpr unsigned DefaultSectionAlign = 4;
|
||||||
|
constexpr int16_t MaxSectionIndex = INT16_MAX;
|
||||||
|
|
||||||
// Packs the csect's alignment and type into a byte.
|
// Packs the csect's alignment and type into a byte.
|
||||||
uint8_t getEncodedType(const MCSectionXCOFF *);
|
uint8_t getEncodedType(const MCSectionXCOFF *);
|
||||||
|
@ -73,6 +74,22 @@ struct ControlSection {
|
||||||
: MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
|
: MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Type to be used for a container representing a set of csects with
|
||||||
|
// (approximately) the same storage mapping class. For example all the csects
|
||||||
|
// with a storage mapping class of `xmc_pr` will get placed into the same
|
||||||
|
// container.
|
||||||
|
struct CsectGroup {
|
||||||
|
enum LabelDefinitionSupport : bool {
|
||||||
|
LabelDefSupported = true,
|
||||||
|
LabelDefUnsupported = false
|
||||||
|
};
|
||||||
|
|
||||||
|
const LabelDefinitionSupport SupportLabelDef;
|
||||||
|
std::deque<ControlSection> Csects;
|
||||||
|
};
|
||||||
|
|
||||||
|
using CsectGroups = std::deque<CsectGroup *>;
|
||||||
|
|
||||||
// Represents the data related to a section excluding the csects that make up
|
// Represents the data related to a section excluding the csects that make up
|
||||||
// the raw data of the section. The csects are stored separately as not all
|
// the raw data of the section. The csects are stored separately as not all
|
||||||
// sections contain csects, and some sections contain csects which are better
|
// sections contain csects, and some sections contain csects which are better
|
||||||
|
@ -94,49 +111,63 @@ struct Section {
|
||||||
// Virtual sections do not need storage allocated in the object file.
|
// Virtual sections do not need storage allocated in the object file.
|
||||||
const bool IsVirtual;
|
const bool IsVirtual;
|
||||||
|
|
||||||
|
// XCOFF has special section numbers for symbols:
|
||||||
|
// -2 Specifies N_DEBUG, a special symbolic debugging symbol.
|
||||||
|
// -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
|
||||||
|
// relocatable.
|
||||||
|
// 0 Specifies N_UNDEF, an undefined external symbol.
|
||||||
|
// Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
|
||||||
|
// hasn't been initialized.
|
||||||
|
static constexpr int16_t UninitializedIndex =
|
||||||
|
XCOFF::ReservedSectionNum::N_DEBUG - 1;
|
||||||
|
|
||||||
|
CsectGroups Groups;
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
Address = 0;
|
Address = 0;
|
||||||
Size = 0;
|
Size = 0;
|
||||||
FileOffsetToData = 0;
|
FileOffsetToData = 0;
|
||||||
FileOffsetToRelocations = 0;
|
FileOffsetToRelocations = 0;
|
||||||
RelocationCount = 0;
|
RelocationCount = 0;
|
||||||
Index = -1;
|
Index = UninitializedIndex;
|
||||||
|
// Clear any csects we have stored.
|
||||||
|
for (auto *Group : Groups)
|
||||||
|
Group->Csects.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual)
|
Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
|
||||||
|
CsectGroups Groups)
|
||||||
: Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0),
|
: Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0),
|
||||||
RelocationCount(0), Flags(Flags), Index(-1), IsVirtual(IsVirtual) {
|
RelocationCount(0), Flags(Flags), Index(UninitializedIndex),
|
||||||
|
IsVirtual(IsVirtual), Groups(Groups) {
|
||||||
strncpy(Name, N, XCOFF::NameSize);
|
strncpy(Name, N, XCOFF::NameSize);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class XCOFFObjectWriter : public MCObjectWriter {
|
class XCOFFObjectWriter : public MCObjectWriter {
|
||||||
// Type to be used for a container representing a set of csects with
|
|
||||||
// (approximately) the same storage mapping class. For example all the csects
|
uint32_t SymbolTableEntryCount = 0;
|
||||||
// with a storage mapping class of `xmc_pr` will get placed into the same
|
uint32_t SymbolTableOffset = 0;
|
||||||
// container.
|
|
||||||
using CsectGroup = std::deque<ControlSection>;
|
|
||||||
|
|
||||||
support::endian::Writer W;
|
support::endian::Writer W;
|
||||||
std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
|
std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
|
||||||
StringTableBuilder Strings;
|
StringTableBuilder Strings;
|
||||||
|
|
||||||
// The non-empty sections, in the order they will appear in the section header
|
// CsectGroups. These store the csects which make up different parts of
|
||||||
// table.
|
// the sections. Should have one for each set of csects that get mapped into
|
||||||
std::vector<Section *> Sections;
|
// the same section and get handled in a 'similar' way.
|
||||||
|
CsectGroup ProgramCodeCsects{CsectGroup::LabelDefSupported};
|
||||||
|
CsectGroup BSSCsects{CsectGroup::LabelDefUnsupported};
|
||||||
|
|
||||||
// The Predefined sections.
|
// The Predefined sections.
|
||||||
Section Text;
|
Section Text;
|
||||||
Section BSS;
|
Section BSS;
|
||||||
|
|
||||||
// CsectGroups. These store the csects which make up different parts of
|
// All the XCOFF sections, in the order they will appear in the section header
|
||||||
// the sections. Should have one for each set of csects that get mapped into
|
// table.
|
||||||
// the same section and get handled in a 'similar' way.
|
std::array<Section *const, 2> Sections{&Text, &BSS};
|
||||||
CsectGroup ProgramCodeCsects;
|
|
||||||
CsectGroup BSSCsects;
|
|
||||||
|
|
||||||
uint32_t SymbolTableEntryCount = 0;
|
CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
|
||||||
uint32_t SymbolTableOffset = 0;
|
|
||||||
|
|
||||||
virtual void reset() override;
|
virtual void reset() override;
|
||||||
|
|
||||||
|
@ -190,18 +221,15 @@ XCOFFObjectWriter::XCOFFObjectWriter(
|
||||||
std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
|
std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
|
||||||
: W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
|
: W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
|
||||||
Strings(StringTableBuilder::XCOFF),
|
Strings(StringTableBuilder::XCOFF),
|
||||||
Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false),
|
Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
|
||||||
BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true) {}
|
CsectGroups{&ProgramCodeCsects}),
|
||||||
|
BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
|
||||||
|
CsectGroups{&BSSCsects}) {}
|
||||||
|
|
||||||
void XCOFFObjectWriter::reset() {
|
void XCOFFObjectWriter::reset() {
|
||||||
// Reset any sections we have written to, and empty the section header table.
|
// Reset any sections we have written to, and empty the section header table.
|
||||||
for (auto *Sec : Sections)
|
for (auto *Sec : Sections)
|
||||||
Sec->reset();
|
Sec->reset();
|
||||||
Sections.clear();
|
|
||||||
|
|
||||||
// Clear any csects we have stored.
|
|
||||||
ProgramCodeCsects.clear();
|
|
||||||
BSSCsects.clear();
|
|
||||||
|
|
||||||
// Reset the symbol table and string table.
|
// Reset the symbol table and string table.
|
||||||
SymbolTableEntryCount = 0;
|
SymbolTableEntryCount = 0;
|
||||||
|
@ -211,6 +239,27 @@ void XCOFFObjectWriter::reset() {
|
||||||
MCObjectWriter::reset();
|
MCObjectWriter::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
|
||||||
|
switch (MCSec->getMappingClass()) {
|
||||||
|
case XCOFF::XMC_PR:
|
||||||
|
assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
|
||||||
|
"Only an initialized csect can contain program code.");
|
||||||
|
return ProgramCodeCsects;
|
||||||
|
case XCOFF::XMC_RW:
|
||||||
|
if (XCOFF::XTY_CM == MCSec->getCSectType())
|
||||||
|
return BSSCsects;
|
||||||
|
|
||||||
|
report_fatal_error("Unhandled mapping of read-write csect to section.");
|
||||||
|
case XCOFF::XMC_BS:
|
||||||
|
assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
|
||||||
|
"Mapping invalid csect. CSECT with bss storage class must be "
|
||||||
|
"common type.");
|
||||||
|
return BSSCsects;
|
||||||
|
default:
|
||||||
|
report_fatal_error("Unhandled mapping of csect to section.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
|
void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
|
||||||
const MCAsmLayout &Layout) {
|
const MCAsmLayout &Layout) {
|
||||||
if (TargetObjectWriter->is64Bit())
|
if (TargetObjectWriter->is64Bit())
|
||||||
|
@ -231,33 +280,13 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
|
||||||
if (nameShouldBeInStringTable(MCSec->getSectionName()))
|
if (nameShouldBeInStringTable(MCSec->getSectionName()))
|
||||||
Strings.add(MCSec->getSectionName());
|
Strings.add(MCSec->getSectionName());
|
||||||
|
|
||||||
switch (MCSec->getMappingClass()) {
|
// TODO FIXME Handle emiting the TOC base.
|
||||||
case XCOFF::XMC_PR:
|
if (MCSec->getMappingClass() == XCOFF::XMC_TC0)
|
||||||
assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
|
continue;
|
||||||
"Only an initialized csect can contain program code.");
|
|
||||||
ProgramCodeCsects.emplace_back(MCSec);
|
CsectGroup &Group = getCsectGroup(MCSec);
|
||||||
WrapperMap[MCSec] = &ProgramCodeCsects.back();
|
Group.Csects.emplace_back(MCSec);
|
||||||
break;
|
WrapperMap[MCSec] = &Group.Csects.back();
|
||||||
case XCOFF::XMC_RW:
|
|
||||||
if (XCOFF::XTY_CM == MCSec->getCSectType()) {
|
|
||||||
BSSCsects.emplace_back(MCSec);
|
|
||||||
WrapperMap[MCSec] = &BSSCsects.back();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
report_fatal_error("Unhandled mapping of read-write csect to section.");
|
|
||||||
case XCOFF::XMC_TC0:
|
|
||||||
// TODO FIXME Handle emiting the TOC base.
|
|
||||||
break;
|
|
||||||
case XCOFF::XMC_BS:
|
|
||||||
assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
|
|
||||||
"Mapping invalid csect. CSECT with bss storage class must be "
|
|
||||||
"common type.");
|
|
||||||
BSSCsects.emplace_back(MCSec);
|
|
||||||
WrapperMap[MCSec] = &BSSCsects.back();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
report_fatal_error("Unhandled mapping of csect to section.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const MCSymbol &S : Asm.symbols()) {
|
for (const MCSymbol &S : Asm.symbols()) {
|
||||||
|
@ -292,21 +321,28 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &,
|
||||||
|
|
||||||
void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
|
void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
|
||||||
const MCAsmLayout &Layout) {
|
const MCAsmLayout &Layout) {
|
||||||
// Write the program code control sections one at a time.
|
uint32_t CurrentAddressLocation = 0;
|
||||||
uint32_t CurrentAddressLocation = Text.Address;
|
for (const auto *Section : Sections) {
|
||||||
for (const auto &Csect : ProgramCodeCsects) {
|
// Nothing to write for this Section.
|
||||||
if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
|
if (Section->Index == Section::UninitializedIndex || Section->IsVirtual)
|
||||||
W.OS.write_zeros(PaddingSize);
|
continue;
|
||||||
Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
|
|
||||||
CurrentAddressLocation = Csect.Address + Csect.Size;
|
assert(CurrentAddressLocation == Section->Address &&
|
||||||
}
|
"We should have no padding between sections.");
|
||||||
|
for (const auto *Group : Section->Groups) {
|
||||||
|
for (const auto &Csect : Group->Csects) {
|
||||||
|
if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
|
||||||
|
W.OS.write_zeros(PaddingSize);
|
||||||
|
Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
|
||||||
|
CurrentAddressLocation = Csect.Address + Csect.Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Text.Index != -1) {
|
|
||||||
// The size of the tail padding in a section is the end virtual address of
|
// The size of the tail padding in a section is the end virtual address of
|
||||||
// the current section minus the the end virtual address of the last csect
|
// the current section minus the the end virtual address of the last csect
|
||||||
// in that section.
|
// in that section.
|
||||||
if (uint32_t PaddingSize =
|
if (uint32_t PaddingSize =
|
||||||
Text.Address + Text.Size - CurrentAddressLocation)
|
Section->Address + Section->Size - CurrentAddressLocation)
|
||||||
W.OS.write_zeros(PaddingSize);
|
W.OS.write_zeros(PaddingSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -472,25 +508,28 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
|
void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
|
||||||
// Print out symbol table for the program code.
|
for (const auto *Section : Sections) {
|
||||||
for (const auto &Csect : ProgramCodeCsects) {
|
for (const auto *Group : Section->Groups) {
|
||||||
// Write out the control section first and then each symbol in it.
|
if (Group->Csects.empty())
|
||||||
writeSymbolTableEntryForControlSection(Csect, Text.Index,
|
continue;
|
||||||
Csect.MCCsect->getStorageClass());
|
|
||||||
for (const auto &Sym : Csect.Syms)
|
|
||||||
writeSymbolTableEntryForCsectMemberLabel(
|
|
||||||
Sym, Csect, Text.Index, Layout.getSymbolOffset(*Sym.MCSym));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The BSS Section is special in that the csects must contain a single symbol,
|
const bool SupportLabelDef = Group->SupportLabelDef;
|
||||||
// and the contained symbol cannot be represented in the symbol table as a
|
const int16_t SectionIndex = Section->Index;
|
||||||
// label definition.
|
for (const auto &Csect : Group->Csects) {
|
||||||
for (auto &Csect : BSSCsects) {
|
// Write out the control section first and then each symbol in it.
|
||||||
assert(Csect.Syms.size() == 1 &&
|
writeSymbolTableEntryForControlSection(
|
||||||
"Uninitialized csect cannot contain more then 1 symbol.");
|
Csect, SectionIndex, Csect.MCCsect->getStorageClass());
|
||||||
Symbol &Sym = Csect.Syms.back();
|
if (!SupportLabelDef) {
|
||||||
writeSymbolTableEntryForControlSection(Csect, BSS.Index,
|
assert(Csect.Syms.size() == 1 && "Csect should only contain 1 symbol "
|
||||||
Sym.getStorageClass());
|
"which is its label definition.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto Sym : Csect.Syms)
|
||||||
|
writeSymbolTableEntryForCsectMemberLabel(
|
||||||
|
Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,64 +539,59 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
|
||||||
// section header table.
|
// section header table.
|
||||||
uint32_t Address = 0;
|
uint32_t Address = 0;
|
||||||
// Section indices are 1-based in XCOFF.
|
// Section indices are 1-based in XCOFF.
|
||||||
int16_t SectionIndex = 1;
|
int32_t SectionIndex = 1;
|
||||||
// The first symbol table entry is for the file name. We are not emitting it
|
// The first symbol table entry is for the file name. We are not emitting it
|
||||||
// yet, so start at index 0.
|
// yet, so start at index 0.
|
||||||
uint32_t SymbolTableIndex = 0;
|
uint32_t SymbolTableIndex = 0;
|
||||||
|
|
||||||
// Text section comes first.
|
for (auto *Section : Sections) {
|
||||||
if (!ProgramCodeCsects.empty()) {
|
const bool IsEmpty =
|
||||||
Sections.push_back(&Text);
|
llvm::all_of(Section->Groups, [](const CsectGroup *Group) {
|
||||||
Text.Index = SectionIndex++;
|
return Group->Csects.empty();
|
||||||
for (auto &Csect : ProgramCodeCsects) {
|
});
|
||||||
const MCSectionXCOFF *MCSec = Csect.MCCsect;
|
if (IsEmpty)
|
||||||
Csect.Address = alignTo(Address, MCSec->getAlignment());
|
continue;
|
||||||
Csect.Size = Layout.getSectionAddressSize(MCSec);
|
|
||||||
Address = Csect.Address + Csect.Size;
|
if (SectionIndex > MaxSectionIndex)
|
||||||
Csect.SymbolTableIndex = SymbolTableIndex;
|
report_fatal_error("Section index overflow!");
|
||||||
// 1 main and 1 auxiliary symbol table entry for the csect.
|
Section->Index = SectionIndex++;
|
||||||
SymbolTableIndex += 2;
|
|
||||||
for (auto &Sym : Csect.Syms) {
|
bool SectionAddressSet = false;
|
||||||
Sym.SymbolTableIndex = SymbolTableIndex;
|
for (auto *Group : Section->Groups) {
|
||||||
// 1 main and 1 auxiliary symbol table entry for each contained symbol
|
if (Group->Csects.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const bool SupportLabelDef = Group->SupportLabelDef;
|
||||||
|
for (auto &Csect : Group->Csects) {
|
||||||
|
const MCSectionXCOFF *MCSec = Csect.MCCsect;
|
||||||
|
Csect.Address = alignTo(Address, MCSec->getAlignment());
|
||||||
|
Csect.Size = Layout.getSectionAddressSize(MCSec);
|
||||||
|
Address = Csect.Address + Csect.Size;
|
||||||
|
Csect.SymbolTableIndex = SymbolTableIndex;
|
||||||
|
// 1 main and 1 auxiliary symbol table entry for the csect.
|
||||||
SymbolTableIndex += 2;
|
SymbolTableIndex += 2;
|
||||||
|
|
||||||
|
if (!SupportLabelDef)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (auto &Sym : Csect.Syms) {
|
||||||
|
Sym.SymbolTableIndex = SymbolTableIndex;
|
||||||
|
// 1 main and 1 auxiliary symbol table entry for each contained
|
||||||
|
// symbol.
|
||||||
|
SymbolTableIndex += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SectionAddressSet) {
|
||||||
|
Section->Address = Group->Csects.front().Address;
|
||||||
|
SectionAddressSet = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure the address of the next section aligned to
|
||||||
|
// DefaultSectionAlign.
|
||||||
Address = alignTo(Address, DefaultSectionAlign);
|
Address = alignTo(Address, DefaultSectionAlign);
|
||||||
|
Section->Size = Address - Section->Address;
|
||||||
// The first csect of a section can be aligned by adjusting the virtual
|
|
||||||
// address of its containing section instead of writing zeroes into the
|
|
||||||
// object file.
|
|
||||||
Text.Address = ProgramCodeCsects.front().Address;
|
|
||||||
|
|
||||||
Text.Size = Address - Text.Address;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data section Second. TODO
|
|
||||||
|
|
||||||
// BSS Section third.
|
|
||||||
if (!BSSCsects.empty()) {
|
|
||||||
Sections.push_back(&BSS);
|
|
||||||
BSS.Index = SectionIndex++;
|
|
||||||
for (auto &Csect : BSSCsects) {
|
|
||||||
const MCSectionXCOFF *MCSec = Csect.MCCsect;
|
|
||||||
Csect.Address = alignTo(Address, MCSec->getAlignment());
|
|
||||||
Csect.Size = Layout.getSectionAddressSize(MCSec);
|
|
||||||
Address = Csect.Address + Csect.Size;
|
|
||||||
Csect.SymbolTableIndex = SymbolTableIndex;
|
|
||||||
// 1 main and 1 auxiliary symbol table entry for the csect.
|
|
||||||
SymbolTableIndex += 2;
|
|
||||||
|
|
||||||
assert(Csect.Syms.size() == 1 &&
|
|
||||||
"csect in the BSS can only contain a single symbol.");
|
|
||||||
Csect.Syms[0].SymbolTableIndex = Csect.SymbolTableIndex;
|
|
||||||
}
|
|
||||||
// Pad out Address to the default alignment. This is to match how the system
|
|
||||||
// assembler handles the .bss section. Its size is always a multiple of 4.
|
|
||||||
Address = alignTo(Address, DefaultSectionAlign);
|
|
||||||
|
|
||||||
BSS.Address = BSSCsects.front().Address;
|
|
||||||
BSS.Size = Address - BSS.Address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolTableEntryCount = SymbolTableIndex;
|
SymbolTableEntryCount = SymbolTableIndex;
|
||||||
|
|
Loading…
Reference in New Issue