Skip to content

Commit abdb2d2

Browse files
committed
[MC] Allow MCObjectWriter's output stream to be swapped out
There are occasions where it is useful to consider the entirety of the contents of a section. For example, compressed debug info needs the entire section available before it can compress it and write it out. The compressed debug info scenario was previously implemented by mirroring the implementation of writeSectionData in the ELFObjectWriter. Instead, allow the output stream to be swapped on demand. This lets callers redirect the output stream to a more convenient location before it hits the object file. No functionality change is intended. Differential Revision: http://reviews.llvm.org/D12509 llvm-svn: 246554
1 parent 491d3bf commit abdb2d2

File tree

4 files changed

+73
-93
lines changed

4 files changed

+73
-93
lines changed

llvm/include/llvm/MC/MCObjectWriter.h

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ class MCObjectWriter {
4040
MCObjectWriter(const MCObjectWriter &) = delete;
4141
void operator=(const MCObjectWriter &) = delete;
4242

43-
protected:
44-
raw_pwrite_stream &OS;
43+
raw_pwrite_stream *OS;
4544

45+
protected:
4646
unsigned IsLittleEndian : 1;
4747

4848
protected: // Can only create subclasses.
4949
MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian)
50-
: OS(OS), IsLittleEndian(IsLittleEndian) {}
50+
: OS(&OS), IsLittleEndian(IsLittleEndian) {}
5151

5252
public:
5353
virtual ~MCObjectWriter();
@@ -57,7 +57,8 @@ class MCObjectWriter {
5757

5858
bool isLittleEndian() const { return IsLittleEndian; }
5959

60-
raw_ostream &getStream() { return OS; }
60+
raw_pwrite_stream &getStream() { return *OS; }
61+
void setStream(raw_pwrite_stream &NewOS) { OS = &NewOS; }
6162

6263
/// \name High-Level API
6364
/// @{
@@ -113,30 +114,30 @@ class MCObjectWriter {
113114
/// \name Binary Output
114115
/// @{
115116

116-
void write8(uint8_t Value) { OS << char(Value); }
117+
void write8(uint8_t Value) { *OS << char(Value); }
117118

118119
void writeLE16(uint16_t Value) {
119-
support::endian::Writer<support::little>(OS).write(Value);
120+
support::endian::Writer<support::little>(*OS).write(Value);
120121
}
121122

122123
void writeLE32(uint32_t Value) {
123-
support::endian::Writer<support::little>(OS).write(Value);
124+
support::endian::Writer<support::little>(*OS).write(Value);
124125
}
125126

126127
void writeLE64(uint64_t Value) {
127-
support::endian::Writer<support::little>(OS).write(Value);
128+
support::endian::Writer<support::little>(*OS).write(Value);
128129
}
129130

130131
void writeBE16(uint16_t Value) {
131-
support::endian::Writer<support::big>(OS).write(Value);
132+
support::endian::Writer<support::big>(*OS).write(Value);
132133
}
133134

134135
void writeBE32(uint32_t Value) {
135-
support::endian::Writer<support::big>(OS).write(Value);
136+
support::endian::Writer<support::big>(*OS).write(Value);
136137
}
137138

138139
void writeBE64(uint64_t Value) {
139-
support::endian::Writer<support::big>(OS).write(Value);
140+
support::endian::Writer<support::big>(*OS).write(Value);
140141
}
141142

142143
void write16(uint16_t Value) {
@@ -164,9 +165,9 @@ class MCObjectWriter {
164165
const char Zeros[16] = {0};
165166

166167
for (unsigned i = 0, e = N / 16; i != e; ++i)
167-
OS << StringRef(Zeros, 16);
168+
*OS << StringRef(Zeros, 16);
168169

169-
OS << StringRef(Zeros, N % 16);
170+
*OS << StringRef(Zeros, N % 16);
170171
}
171172

172173
void writeBytes(const SmallVectorImpl<char> &ByteVec,
@@ -180,7 +181,7 @@ class MCObjectWriter {
180181
assert(
181182
(ZeroFillSize == 0 || Str.size() <= ZeroFillSize) &&
182183
"data size greater than fill size, unexpected large write will occur");
183-
OS << Str;
184+
*OS << Str;
184185
if (ZeroFillSize)
185186
WriteZeros(ZeroFillSize - Str.size());
186187
}

llvm/lib/MC/ELFObjectWriter.cpp

Lines changed: 32 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@ class ELFObjectWriter : public MCObjectWriter {
157157

158158
template <typename T> void write(T Val) {
159159
if (IsLittleEndian)
160-
support::endian::Writer<support::little>(OS).write(Val);
160+
support::endian::Writer<support::little>(getStream()).write(Val);
161161
else
162-
support::endian::Writer<support::big>(OS).write(Val);
162+
support::endian::Writer<support::big>(getStream()).write(Val);
163163
}
164164

165165
void writeHeader(const MCAssembler &Asm);
@@ -232,7 +232,7 @@ class ELFObjectWriter : public MCObjectWriter {
232232
}
233233

234234
void ELFObjectWriter::align(unsigned Alignment) {
235-
uint64_t Padding = OffsetToAlignment(OS.tell(), Alignment);
235+
uint64_t Padding = OffsetToAlignment(getStream().tell(), Alignment);
236236
WriteZeros(Padding);
237237
}
238238

@@ -764,7 +764,7 @@ void ELFObjectWriter::computeSymbolTable(
764764
SymbolTableIndex = addToSectionTable(SymtabSection);
765765

766766
align(SymtabSection->getAlignment());
767-
uint64_t SecStart = OS.tell();
767+
uint64_t SecStart = getStream().tell();
768768

769769
// The first entry is the undefined symbol entry.
770770
Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
@@ -911,7 +911,7 @@ void ELFObjectWriter::computeSymbolTable(
911911
assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL);
912912
}
913913

914-
uint64_t SecEnd = OS.tell();
914+
uint64_t SecEnd = getStream().tell();
915915
SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd);
916916

917917
ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
@@ -921,12 +921,12 @@ void ELFObjectWriter::computeSymbolTable(
921921
}
922922
assert(SymtabShndxSectionIndex != 0);
923923

924-
SecStart = OS.tell();
924+
SecStart = getStream().tell();
925925
const MCSectionELF *SymtabShndxSection =
926926
SectionTable[SymtabShndxSectionIndex - 1];
927927
for (uint32_t Index : ShndxIndexes)
928928
write(Index);
929-
SecEnd = OS.tell();
929+
SecEnd = getStream().tell();
930930
SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd);
931931
}
932932

@@ -957,31 +957,6 @@ ELFObjectWriter::createRelocationSection(MCContext &Ctx,
957957
return RelaSection;
958958
}
959959

960-
static SmallVector<char, 128>
961-
getUncompressedData(const MCAsmLayout &Layout,
962-
const MCSection::FragmentListType &Fragments) {
963-
SmallVector<char, 128> UncompressedData;
964-
for (const MCFragment &F : Fragments) {
965-
const SmallVectorImpl<char> *Contents;
966-
switch (F.getKind()) {
967-
case MCFragment::FT_Data:
968-
Contents = &cast<MCDataFragment>(F).getContents();
969-
break;
970-
case MCFragment::FT_Dwarf:
971-
Contents = &cast<MCDwarfLineAddrFragment>(F).getContents();
972-
break;
973-
case MCFragment::FT_DwarfFrame:
974-
Contents = &cast<MCDwarfCallFrameFragment>(F).getContents();
975-
break;
976-
default:
977-
llvm_unreachable(
978-
"Not expecting any other fragment types in a debug_* section");
979-
}
980-
UncompressedData.append(Contents->begin(), Contents->end());
981-
}
982-
return UncompressedData;
983-
}
984-
985960
// Include the debug info compression header:
986961
// "ZLIB" followed by 8 bytes representing the uncompressed size of the section,
987962
// useful for consumers to preallocate a buffer to decompress into.
@@ -1016,27 +991,29 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
1016991
return;
1017992
}
1018993

1019-
// Gather the uncompressed data from all the fragments.
1020-
const MCSection::FragmentListType &Fragments = Section.getFragmentList();
1021-
SmallVector<char, 128> UncompressedData =
1022-
getUncompressedData(Layout, Fragments);
994+
SmallVector<char, 128> UncompressedData;
995+
raw_svector_ostream VecOS(UncompressedData);
996+
raw_pwrite_stream &OldStream = getStream();
997+
setStream(VecOS);
998+
Asm.writeSectionData(&Section, Layout);
999+
setStream(OldStream);
10231000

10241001
SmallVector<char, 128> CompressedContents;
10251002
zlib::Status Success = zlib::compress(
10261003
StringRef(UncompressedData.data(), UncompressedData.size()),
10271004
CompressedContents);
10281005
if (Success != zlib::StatusOK) {
1029-
Asm.writeSectionData(&Section, Layout);
1006+
getStream() << UncompressedData;
10301007
return;
10311008
}
10321009

10331010
if (!prependCompressionHeader(UncompressedData.size(), CompressedContents)) {
1034-
Asm.writeSectionData(&Section, Layout);
1011+
getStream() << UncompressedData;
10351012
return;
10361013
}
10371014
Asm.getContext().renameELFSection(&Section,
10381015
(".z" + SectionName.drop_front(1)).str());
1039-
OS << CompressedContents;
1016+
getStream() << CompressedContents;
10401017
}
10411018

10421019
void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
@@ -1100,7 +1077,7 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
11001077

11011078
const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) {
11021079
const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1];
1103-
OS << StrTabBuilder.data();
1080+
getStream() << StrTabBuilder.data();
11041081
return StrtabSection;
11051082
}
11061083

@@ -1209,12 +1186,12 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
12091186
align(Section.getAlignment());
12101187

12111188
// Remember the offset into the file for this section.
1212-
uint64_t SecStart = OS.tell();
1189+
uint64_t SecStart = getStream().tell();
12131190

12141191
const MCSymbolELF *SignatureSymbol = Section.getGroup();
12151192
writeSectionData(Asm, Section, Layout);
12161193

1217-
uint64_t SecEnd = OS.tell();
1194+
uint64_t SecEnd = getStream().tell();
12181195
SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd);
12191196

12201197
MCSectionELF *RelSection = createRelocationSection(Ctx, Section);
@@ -1246,7 +1223,7 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
12461223
align(Group->getAlignment());
12471224

12481225
// Remember the offset into the file for this section.
1249-
uint64_t SecStart = OS.tell();
1226+
uint64_t SecStart = getStream().tell();
12501227

12511228
const MCSymbol *SignatureSymbol = Group->getGroup();
12521229
assert(SignatureSymbol);
@@ -1256,7 +1233,7 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
12561233
write(SecIndex);
12571234
}
12581235

1259-
uint64_t SecEnd = OS.tell();
1236+
uint64_t SecEnd = getStream().tell();
12601237
SectionOffsets[Group] = std::make_pair(SecStart, SecEnd);
12611238
}
12621239

@@ -1267,25 +1244,25 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
12671244
align(RelSection->getAlignment());
12681245

12691246
// Remember the offset into the file for this section.
1270-
uint64_t SecStart = OS.tell();
1247+
uint64_t SecStart = getStream().tell();
12711248

12721249
writeRelocations(Asm, *RelSection->getAssociatedSection());
12731250

1274-
uint64_t SecEnd = OS.tell();
1251+
uint64_t SecEnd = getStream().tell();
12751252
SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
12761253
}
12771254

12781255
{
1279-
uint64_t SecStart = OS.tell();
1256+
uint64_t SecStart = getStream().tell();
12801257
const MCSectionELF *Sec = createStringTable(Ctx);
1281-
uint64_t SecEnd = OS.tell();
1258+
uint64_t SecEnd = getStream().tell();
12821259
SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
12831260
}
12841261

12851262
uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
12861263
align(NaturalAlignment);
12871264

1288-
const unsigned SectionHeaderOffset = OS.tell();
1265+
const unsigned SectionHeaderOffset = getStream().tell();
12891266

12901267
// ... then the section header table ...
12911268
writeSectionHeader(Layout, SectionIndexMap, SectionOffsets);
@@ -1301,19 +1278,19 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
13011278
uint64_t Val = SectionHeaderOffset;
13021279
if (sys::IsLittleEndianHost != IsLittleEndian)
13031280
sys::swapByteOrder(Val);
1304-
OS.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
1305-
offsetof(ELF::Elf64_Ehdr, e_shoff));
1281+
getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
1282+
offsetof(ELF::Elf64_Ehdr, e_shoff));
13061283
NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
13071284
} else {
13081285
uint32_t Val = SectionHeaderOffset;
13091286
if (sys::IsLittleEndianHost != IsLittleEndian)
13101287
sys::swapByteOrder(Val);
1311-
OS.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
1312-
offsetof(ELF::Elf32_Ehdr, e_shoff));
1288+
getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
1289+
offsetof(ELF::Elf32_Ehdr, e_shoff));
13131290
NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
13141291
}
1315-
OS.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),
1316-
NumSectionsOffset);
1292+
getStream().pwrite(reinterpret_cast<char *>(&NumSections),
1293+
sizeof(NumSections), NumSectionsOffset);
13171294
}
13181295

13191296
bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(

0 commit comments

Comments
 (0)