Add support for files with more than 65280 sections. No testcase since

it would be a bit too big :-)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117849 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola
2010-10-31 00:16:26 +00:00
parent 76d61478df
commit 7be2c33193
2 changed files with 110 additions and 42 deletions

View File

@ -299,6 +299,7 @@ enum {
SHN_HIPROC = 0xff1f, // Highest processor-specific index SHN_HIPROC = 0xff1f, // Highest processor-specific index
SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation
SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables
SHN_XINDEX = 0xffff, // Mark that the index is >= SHN_LORESERVE
SHN_HIRESERVE = 0xffff // Highest reserved index SHN_HIRESERVE = 0xffff // Highest reserved index
}; };

View File

@ -164,6 +164,8 @@ namespace {
bool NeedsGOT; bool NeedsGOT;
bool NeedsSymtabShndx;
ELFObjectWriter *Writer; ELFObjectWriter *Writer;
raw_ostream &OS; raw_ostream &OS;
@ -180,6 +182,8 @@ namespace {
unsigned LastLocalSymbolIndex; unsigned LastLocalSymbolIndex;
// This holds the .strtab section index. // This holds the .strtab section index.
unsigned StringTableIndex; unsigned StringTableIndex;
// This holds the .symtab section index.
unsigned SymbolTableIndex;
unsigned ShstrtabIndex; unsigned ShstrtabIndex;
@ -187,7 +191,8 @@ namespace {
ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit, ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit,
uint16_t _EMachine, bool _HasRelAddend, uint16_t _EMachine, bool _HasRelAddend,
Triple::OSType _OSType) Triple::OSType _OSType)
: NeedsGOT(false), Writer(_Writer), OS(Writer->getStream()), : NeedsGOT(false), NeedsSymtabShndx(false), Writer(_Writer),
OS(Writer->getStream()),
Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend), Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend),
OSType(_OSType), EMachine(_EMachine) { OSType(_OSType), EMachine(_EMachine) {
} }
@ -265,14 +270,18 @@ namespace {
void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections); void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections);
void WriteSymbolEntry(MCDataFragment *F, uint64_t name, uint8_t info, void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
uint64_t name, uint8_t info,
uint64_t value, uint64_t size, uint64_t value, uint64_t size,
uint8_t other, uint16_t shndx); uint8_t other, uint32_t shndx,
bool Reserved);
void WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD, void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
ELFSymbolData &MSD,
const MCAsmLayout &Layout); const MCAsmLayout &Layout);
void WriteSymbolTable(MCDataFragment *F, const MCAssembler &Asm, void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
const MCAssembler &Asm,
const MCAsmLayout &Layout, const MCAsmLayout &Layout,
unsigned NumRegularSections); unsigned NumRegularSections);
@ -377,56 +386,82 @@ void ELFObjectWriterImpl::WriteHeader(uint64_t SectionDataSize,
Write16(Is64Bit ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr)); Write16(Is64Bit ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
// e_shnum = # of section header ents // e_shnum = # of section header ents
Write16(NumberOfSections); if (NumberOfSections >= ELF::SHN_LORESERVE)
Write16(0);
else
Write16(NumberOfSections);
// e_shstrndx = Section # of '.shstrtab' // e_shstrndx = Section # of '.shstrtab'
Write16(ShstrtabIndex); if (NumberOfSections >= ELF::SHN_LORESERVE)
Write16(ELF::SHN_XINDEX);
else
Write16(ShstrtabIndex);
} }
void ELFObjectWriterImpl::WriteSymbolEntry(MCDataFragment *F, uint64_t name, void ELFObjectWriterImpl::WriteSymbolEntry(MCDataFragment *SymtabF,
MCDataFragment *ShndxF,
uint64_t name,
uint8_t info, uint64_t value, uint8_t info, uint64_t value,
uint64_t size, uint8_t other, uint64_t size, uint8_t other,
uint16_t shndx) { uint32_t shndx,
bool Reserved) {
if (ShndxF) {
char buf[4];
if (shndx >= ELF::SHN_LORESERVE && !Reserved)
String32(buf, shndx);
else
String32(buf, 0);
ShndxF->getContents() += StringRef(buf, 4);
}
if (Is64Bit) { if (Is64Bit) {
char buf[8]; char buf[8];
String32(buf, name); String32(buf, name);
F->getContents() += StringRef(buf, 4); // st_name SymtabF->getContents() += StringRef(buf, 4); // st_name
String8(buf, info); String8(buf, info);
F->getContents() += StringRef(buf, 1); // st_info SymtabF->getContents() += StringRef(buf, 1); // st_info
String8(buf, other); String8(buf, other);
F->getContents() += StringRef(buf, 1); // st_other SymtabF->getContents() += StringRef(buf, 1); // st_other
String16(buf, shndx); if (shndx >= ELF::SHN_LORESERVE && !Reserved)
F->getContents() += StringRef(buf, 2); // st_shndx String16(buf, ELF::SHN_XINDEX);
else
String16(buf, shndx);
SymtabF->getContents() += StringRef(buf, 2); // st_shndx
String64(buf, value); String64(buf, value);
F->getContents() += StringRef(buf, 8); // st_value SymtabF->getContents() += StringRef(buf, 8); // st_value
String64(buf, size); String64(buf, size);
F->getContents() += StringRef(buf, 8); // st_size SymtabF->getContents() += StringRef(buf, 8); // st_size
} else { } else {
char buf[4]; char buf[4];
String32(buf, name); String32(buf, name);
F->getContents() += StringRef(buf, 4); // st_name SymtabF->getContents() += StringRef(buf, 4); // st_name
String32(buf, value); String32(buf, value);
F->getContents() += StringRef(buf, 4); // st_value SymtabF->getContents() += StringRef(buf, 4); // st_value
String32(buf, size); String32(buf, size);
F->getContents() += StringRef(buf, 4); // st_size SymtabF->getContents() += StringRef(buf, 4); // st_size
String8(buf, info); String8(buf, info);
F->getContents() += StringRef(buf, 1); // st_info SymtabF->getContents() += StringRef(buf, 1); // st_info
String8(buf, other); String8(buf, other);
F->getContents() += StringRef(buf, 1); // st_other SymtabF->getContents() += StringRef(buf, 1); // st_other
String16(buf, shndx); if (shndx >= ELF::SHN_LORESERVE && !Reserved)
F->getContents() += StringRef(buf, 2); // st_shndx String16(buf, ELF::SHN_XINDEX);
else
String16(buf, shndx);
SymtabF->getContents() += StringRef(buf, 2); // st_shndx
} }
} }
@ -503,12 +538,17 @@ void ELFObjectWriterImpl::ExecutePostLayoutBinding(MCAssembler &Asm) {
} }
} }
void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD, void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *SymtabF,
MCDataFragment *ShndxF,
ELFSymbolData &MSD,
const MCAsmLayout &Layout) { const MCAsmLayout &Layout) {
MCSymbolData &OrigData = *MSD.SymbolData; MCSymbolData &OrigData = *MSD.SymbolData;
MCSymbolData &Data = MCSymbolData &Data =
Layout.getAssembler().getSymbolData(AliasedSymbol(OrigData.getSymbol())); Layout.getAssembler().getSymbolData(AliasedSymbol(OrigData.getSymbol()));
bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() ||
Data.getSymbol().isVariable();
uint8_t Binding = GetBinding(OrigData); uint8_t Binding = GetBinding(OrigData);
uint8_t Visibility = GetVisibility(OrigData); uint8_t Visibility = GetVisibility(OrigData);
uint8_t Type = GetType(Data); uint8_t Type = GetType(Data);
@ -541,11 +581,12 @@ void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
} }
// Write out the symbol table entry // Write out the symbol table entry
WriteSymbolEntry(F, MSD.StringIndex, Info, Value, WriteSymbolEntry(SymtabF, ShndxF, MSD.StringIndex, Info, Value,
Size, Other, MSD.SectionIndex); Size, Other, MSD.SectionIndex, IsReserved);
} }
void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F, void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *SymtabF,
MCDataFragment *ShndxF,
const MCAssembler &Asm, const MCAssembler &Asm,
const MCAsmLayout &Layout, const MCAsmLayout &Layout,
unsigned NumRegularSections) { unsigned NumRegularSections) {
@ -556,14 +597,13 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
// FIXME: Make sure the start of the symbol table is aligned. // FIXME: Make sure the start of the symbol table is aligned.
// The first entry is the undefined symbol entry. // The first entry is the undefined symbol entry.
unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32; WriteSymbolEntry(SymtabF, ShndxF, 0, 0, 0, 0, 0, 0, false);
F->getContents().append(EntrySize, '\x00');
// Write the symbol table entries. // Write the symbol table entries.
LastLocalSymbolIndex = LocalSymbolData.size() + 1; LastLocalSymbolIndex = LocalSymbolData.size() + 1;
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) { for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = LocalSymbolData[i]; ELFSymbolData &MSD = LocalSymbolData[i];
WriteSymbol(F, MSD, Layout); WriteSymbol(SymtabF, ShndxF, MSD, Layout);
} }
// Write out a symbol table entry for each regular section. // Write out a symbol table entry for each regular section.
@ -576,7 +616,8 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
// the relocations messed up // the relocations messed up
if (Section.getType() == ELF::SHT_RELA || Section.getType() == ELF::SHT_REL) if (Section.getType() == ELF::SHT_RELA || Section.getType() == ELF::SHT_REL)
continue; continue;
WriteSymbolEntry(F, 0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT, Index); WriteSymbolEntry(SymtabF, ShndxF, 0, ELF::STT_SECTION, 0, 0,
ELF::STV_DEFAULT, Index, false);
LastLocalSymbolIndex++; LastLocalSymbolIndex++;
} }
@ -586,7 +627,7 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
assert(((Data.getFlags() & ELF_STB_Global) || assert(((Data.getFlags() & ELF_STB_Global) ||
(Data.getFlags() & ELF_STB_Weak)) && (Data.getFlags() & ELF_STB_Weak)) &&
"External symbol requires STB_GLOBAL or STB_WEAK flag"); "External symbol requires STB_GLOBAL or STB_WEAK flag");
WriteSymbol(F, MSD, Layout); WriteSymbol(SymtabF, ShndxF, MSD, Layout);
if (GetBinding(Data) == ELF::STB_LOCAL) if (GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++; LastLocalSymbolIndex++;
} }
@ -594,7 +635,7 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) { for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = UndefinedSymbolData[i]; ELFSymbolData &MSD = UndefinedSymbolData[i];
MCSymbolData &Data = *MSD.SymbolData; MCSymbolData &Data = *MSD.SymbolData;
WriteSymbol(F, MSD, Layout); WriteSymbol(SymtabF, ShndxF, MSD, Layout);
if (GetBinding(Data) == ELF::STB_LOCAL) if (GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++; LastLocalSymbolIndex++;
} }
@ -940,6 +981,8 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
MSD.SectionIndex = ELF::SHN_UNDEF; MSD.SectionIndex = ELF::SHN_UNDEF;
} else { } else {
MSD.SectionIndex = SectionIndexMap.lookup(&RefSymbol.getSection()); MSD.SectionIndex = SectionIndexMap.lookup(&RefSymbol.getSection());
if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
NeedsSymtabShndx = true;
assert(MSD.SectionIndex && "Invalid section index!"); assert(MSD.SectionIndex && "Invalid section index!");
} }
@ -1093,24 +1136,35 @@ void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm,
MCContext &Ctx = Asm.getContext(); MCContext &Ctx = Asm.getContext();
MCDataFragment *F; MCDataFragment *F;
const MCSection *SymtabSection;
unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32; unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
unsigned NumRegularSections = Asm.size(); unsigned NumRegularSections = Asm.size();
// We construct .shstrtab, .symtab and .strtab in this order to match gnu as. // We construct .shstrtab, .symtab and .strtab in this order to match gnu as.
const MCSection *ShstrtabSection; const MCSection *ShstrtabSection =
ShstrtabSection = Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0, Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0,
SectionKind::getReadOnly(), false); SectionKind::getReadOnly(), false);
MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection); MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection);
ShstrtabSD.setAlignment(1); ShstrtabSD.setAlignment(1);
ShstrtabIndex = Asm.size(); ShstrtabIndex = Asm.size();
SymtabSection = Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, const MCSection *SymtabSection =
SectionKind::getReadOnly(), Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
false, EntrySize); SectionKind::getReadOnly(),
false, EntrySize);
MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection); MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
SymtabSD.setAlignment(Is64Bit ? 8 : 4); SymtabSD.setAlignment(Is64Bit ? 8 : 4);
SymbolTableIndex = Asm.size();
MCSectionData *SymtabShndxSD = NULL;
if (NeedsSymtabShndx) {
const MCSection *SymtabShndxSection =
Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0,
SectionKind::getReadOnly(), false, 4);
SymtabShndxSD = &Asm.getOrCreateSectionData(*SymtabShndxSection);
SymtabShndxSD->setAlignment(4);
}
const MCSection *StrtabSection; const MCSection *StrtabSection;
StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0, StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0,
@ -1123,7 +1177,12 @@ void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm,
// Symbol table // Symbol table
F = new MCDataFragment(&SymtabSD); F = new MCDataFragment(&SymtabSD);
WriteSymbolTable(F, Asm, Layout, NumRegularSections); MCDataFragment *ShndxF = NULL;
if (NeedsSymtabShndx) {
ShndxF = new MCDataFragment(SymtabShndxSD);
Asm.AddSectionToTheEnd(*Writer, *SymtabShndxSD, Layout);
}
WriteSymbolTable(F, ShndxF, Asm, Layout, NumRegularSections);
Asm.AddSectionToTheEnd(*Writer, SymtabSD, Layout); Asm.AddSectionToTheEnd(*Writer, SymtabSD, Layout);
F = new MCDataFragment(&StrtabSD); F = new MCDataFragment(&StrtabSD);
@ -1255,7 +1314,11 @@ void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm,
// Should we align the section header table? // Should we align the section header table?
// //
// Null section first. // Null section first.
WriteSecHdrEntry(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); uint64_t FirstSectionSize =
NumSections >= ELF::SHN_LORESERVE ? NumSections : 0;
uint32_t FirstSectionLink =
ShstrtabIndex >= ELF::SHN_LORESERVE ? ShstrtabIndex : 0;
WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, FirstSectionLink, 0, 0, 0);
for (MCAssembler::const_iterator it = Asm.begin(), for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) { ie = Asm.end(); it != ie; ++it) {
@ -1300,6 +1363,10 @@ void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm,
sh_info = LastLocalSymbolIndex; sh_info = LastLocalSymbolIndex;
break; break;
case ELF::SHT_SYMTAB_SHNDX:
sh_link = SymbolTableIndex;
break;
case ELF::SHT_PROGBITS: case ELF::SHT_PROGBITS:
case ELF::SHT_STRTAB: case ELF::SHT_STRTAB:
case ELF::SHT_NOBITS: case ELF::SHT_NOBITS: