Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 4c20e87

Browse files
committed
Add abilities to generate bitcode buffers from munged bitcode.
This CL adds capabilities to read/write a munged list of bitcode records. BUG=None [email protected] Review URL: https://codereview.chromium.org/1113023005
1 parent d7d2a80 commit 4c20e87

File tree

10 files changed

+876
-307
lines changed

10 files changed

+876
-307
lines changed

include/llvm/Bitcode/NaCl/NaClBitcodeMunge.h

Lines changed: 39 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Generates a bitcode memory buffer from an array containing 1 or
1414
// more PNaCl records. Used to test errors in PNaCl bitcode.
1515
//
16-
// Bitcode records are modeleled using arrays using the format
16+
// Bitcode records are modeled using arrays using the format
1717
// specified in NaClBitcodeMungeUtils.h.
1818
//
1919
// Note: Since the header record doesn't have any abbreviation indices
@@ -47,7 +47,6 @@
4747

4848
namespace llvm {
4949

50-
class NaClBitstreamWriter;
5150
class NaClBitCodeAbbrev;
5251

5352
/// Base class to run tests on munged bitcode files.
@@ -57,10 +56,21 @@ class NaClBitcodeMunger {
5756
NaClBitcodeMunger(const uint64_t Records[], size_t RecordsSize,
5857
uint64_t RecordTerminator)
5958
: MungedBitcode(Records, RecordsSize, RecordTerminator),
60-
RecordTerminator(RecordTerminator), WriteBlockID(-1), SetBID(-1),
59+
RecordTerminator(RecordTerminator),
6160
DumpResults("Error: No previous dump results!\n"),
62-
DumpStream(nullptr), Writer(nullptr), FoundErrors(false),
63-
FatalBuffer(), FatalStream(FatalBuffer) {}
61+
DumpStream(nullptr), FoundErrors(false), RunAsDeathTest(false) {}
62+
63+
/// Returns true if running as death test.
64+
bool getRunAsDeathTest() const {
65+
return RunAsDeathTest;
66+
}
67+
68+
/// Sets death test flag. When true, output will be redirected to
69+
/// the errs() (rather than buffered) so that the test can be
70+
/// debugged.
71+
void setRunAsDeathTest(bool NewValue) {
72+
RunAsDeathTest = NewValue;
73+
}
6474

6575
/// Creates MungedInput and DumpStream for running tests, based on
6676
/// given Munges.
@@ -88,52 +98,43 @@ class NaClBitcodeMunger {
8898
return getLinesWithTextMatch(Prefix, true);
8999
}
90100

101+
/// When NewValue, use error recovery when writing bitcode during
102+
/// next test.
103+
void setTryToRecoverOnWrite(bool NewValue) {
104+
WriteFlags.setTryToRecover(NewValue);
105+
}
106+
107+
/// When NewValue, write bad abbreviation index into bitcode when
108+
/// writing during next test.
109+
void setWriteBadAbbrevIndex(bool NewValue) {
110+
WriteFlags.setWriteBadAbbrevIndex(NewValue);
111+
}
112+
91113
protected:
92114
// The bitcode records being munged.
93115
NaClMungedBitcode MungedBitcode;
94116
// The value used as record terminator.
95117
uint64_t RecordTerminator;
96-
// The block ID associated with the block being written.
97-
int WriteBlockID;
98-
// The SetBID for the blockinfo block.
99-
int SetBID;
100118
// The results buffer of the last dump.
101119
std::string DumpResults;
102120
// The memory buffer containing the munged input.
103121
std::unique_ptr<MemoryBuffer> MungedInput;
104122
// The stream containing errors and the objdump of the generated bitcode file.
105123
raw_ostream *DumpStream;
106-
// The bitstream writer to use to generate the bitcode file.
107-
NaClBitstreamWriter *Writer;
108124
// True if any errors were reported.
109125
bool FoundErrors;
110-
// The buffer to hold the generated fatal message.
111-
std::string FatalBuffer;
112-
// The stream to write the fatal message to.
113-
raw_string_ostream FatalStream;
114-
// The stack of maximum abbreviation indices allowed by block enter record.
115-
SmallVector<uint64_t, 3> AbbrevIndexLimitStack;
116126
// The buffer for the contents of the munged input.
117127
SmallVector<char, 1024> MungedInputBuffer;
128+
/// The write flags to use when writing bitcode.
129+
NaClMungedBitcode::WriteFlags WriteFlags;
130+
// Flag to redirect dump stream if running death test.
131+
bool RunAsDeathTest;
118132

119133
// Records that an error occurred, and returns stream to print error
120134
// message to.
121135
raw_ostream &Error() {
122136
FoundErrors = true;
123-
return *DumpStream << "Error: ";
124-
}
125-
126-
// Returns stream to print fatal error message to.
127-
// Note: Once the fatal error message has been dumped to the stream,
128-
// one must call ReportFatalError to display the error and terminate
129-
// execution.
130-
raw_ostream &Fatal() {
131-
return FatalStream << "Fatal: ";
132-
}
133-
134-
// Displays the fatal error message and exits the program.
135-
void ReportFatalError() {
136-
report_fatal_error(FatalStream.str());
137+
return getDumpStream() << "Error: ";
137138
}
138139

139140
// Returns the lines containing the given Substring, from the string
@@ -142,14 +143,12 @@ class NaClBitcodeMunger {
142143
std::string getLinesWithTextMatch(const std::string &Substring,
143144
bool MustBePrefix = false) const;
144145

145-
// Writes out munged bitcode records.
146-
void writeMungedBitcode(const NaClMungedBitcode &Bitcode, bool AddHeader);
147-
148-
// Emits the given record to the bitcode file.
149-
void emitRecord(const NaClBitcodeAbbrevRecord &Record);
150-
151-
// Converts the abbreviation record to the corresponding abbreviation.
152-
NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record);
146+
// Returns the log stream to use. When running death tests, redirect output
147+
// to the error stream (rather than buffering in DumpStream), so that
148+
// the output can be seen in gtest death tests.
149+
raw_ostream &getDumpStream() const {
150+
return RunAsDeathTest ? errs() : *DumpStream;
151+
}
153152
};
154153

155154
/// Class to run tests for function llvm::NaClObjDump.
@@ -159,8 +158,7 @@ class NaClObjDumpMunger : public NaClBitcodeMunger {
159158
/// Creates a bitcode munger, based on the given array of values.
160159
NaClObjDumpMunger(const uint64_t Records[], size_t RecordsSize,
161160
uint64_t RecordTerminator)
162-
: NaClBitcodeMunger(Records, RecordsSize, RecordTerminator),
163-
RunAsDeathTest(false) {}
161+
: NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {}
164162

165163
/// Runs function NaClObjDump on the sequence of records associated
166164
/// with the instance. The memory buffer containing the bitsequence
@@ -178,18 +176,6 @@ class NaClObjDumpMunger : public NaClBitcodeMunger {
178176
NoAssembly);
179177
}
180178

181-
/// Returns true if running as death test.
182-
bool getRunAsDeathTest() const {
183-
return RunAsDeathTest;
184-
}
185-
186-
/// Sets death test flag. When true, output will be redirected to
187-
/// the errs() (rather than buffered) so that the test can be
188-
/// debugged.
189-
void setRunAsDeathTest(bool NewValue) {
190-
RunAsDeathTest = NewValue;
191-
}
192-
193179
/// Same as above except it runs function NaClObjDump with flags
194180
/// NoRecords and NoAssembly set to false, and AddHeader set to true.
195181
bool runTest(const char *TestName) {
@@ -235,11 +221,6 @@ class NaClObjDumpMunger : public NaClBitcodeMunger {
235221
size_t MungesSize) {
236222
return runTestWithFlags(TestName, Munges, MungesSize, true, true, true);
237223
}
238-
239-
private:
240-
// Flag to redirect dump stream if running death test.
241-
bool RunAsDeathTest;
242-
243224
};
244225

245226
// Class to run tests for function NaClParseBitcodeFile.

include/llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181

8282
namespace llvm {
8383

84+
class MemoryBuffer; // Buffer to read bitcode from
8485
class NaClBitcodeAbbrevRecord; // bitcode record.
8586
class NaClMungedBitcodeIter; // iterator over edited bitcode records.
8687

@@ -99,6 +100,10 @@ void readNaClBitcodeRecordList(NaClBitcodeRecordList &RecordList,
99100
size_t RecordsSize,
100101
uint64_t RecordTerminator);
101102

103+
/// \brief Read in the list of records from bitcode in a memory buffer.
104+
void readNaClBitcodeRecordList(NaClBitcodeRecordList &RecordList,
105+
std::unique_ptr<MemoryBuffer> InputBuffer);
106+
102107
/// \brief An edited (i.e. munged) list of bitcode records. Edits are
103108
/// always relative to the initial list of records.
104109
class NaClMungedBitcode {
@@ -111,6 +116,9 @@ class NaClMungedBitcode {
111116
/// \brief Iterator over edited records.
112117
typedef NaClMungedBitcodeIter iterator;
113118

119+
/// \brief Read in initial list of records from bitcode in a memory buffer.
120+
explicit NaClMungedBitcode(std::unique_ptr<MemoryBuffer> InputBuffer);
121+
114122
/// \brief Initialize the list of records to be edited.
115123
explicit NaClMungedBitcode(std::unique_ptr<NaClBitcodeRecordList> BaseRecords)
116124
: BaseRecords(std::move(BaseRecords)) {}
@@ -160,6 +168,84 @@ class NaClMungedBitcode {
160168
/// \brief Print out the resulting edited list of records.
161169
void print(raw_ostream &Out) const;
162170

171+
/// Defines set of possible write flags.
172+
struct WriteFlags {
173+
/// True if error recovery should be applied.
174+
bool getTryToRecover() const { return TryToRecover; }
175+
176+
/// Define that error recovery should be applied when writing.
177+
void setTryToRecover(bool NewValue) {
178+
TryToRecover = NewValue;
179+
assert(!(TryToRecover && WriteBadAbbrevIndex));
180+
}
181+
182+
/// True if a bad abbreviation index should be written (rather than
183+
/// trying error recovery) so that bitcode readers can be tested for
184+
/// this condition.
185+
bool getWriteBadAbbrevIndex() const { return WriteBadAbbrevIndex; }
186+
187+
/// Define that the first bad abbreviation index should be written,
188+
/// and corresponding minimal context added so that the bitcode can
189+
/// be used to test reading the erroneous written bitcode.
190+
void setWriteBadAbbrevIndex(bool NewValue) {
191+
WriteBadAbbrevIndex = NewValue;
192+
assert(!(TryToRecover && WriteBadAbbrevIndex));
193+
}
194+
195+
/// Get the stream to print errors while writing bitcode.
196+
raw_ostream &getErrStream() const {
197+
return ErrStream ? *ErrStream : errs();
198+
}
199+
200+
/// Set the stream to print errors to.
201+
void setErrStream(raw_ostream &NewValue) {
202+
ErrStream = &NewValue;
203+
}
204+
205+
void reset() {
206+
TryToRecover = false;
207+
WriteBadAbbrevIndex = false;
208+
ErrStream = nullptr;
209+
}
210+
211+
private:
212+
bool TryToRecover = false;
213+
bool WriteBadAbbrevIndex = false;
214+
raw_ostream *ErrStream = nullptr;
215+
};
216+
217+
/// Defines the results associated with writing bitcode.
218+
struct WriteResults {
219+
/// Number of errors generated.
220+
size_t NumErrors = 0;
221+
/// Number of repairs (via error recovery) that were applied.
222+
size_t NumRepairs = 0;
223+
/// True if a bad abbreviation index were written.
224+
bool WroteBadAbbrevIndex = false;
225+
};
226+
227+
/// \brief Write out the edited list of bitcode records using
228+
/// the given buffer.
229+
///
230+
/// \param Buffer The buffer to write into.
231+
/// \param AddHeader Add header block when true.
232+
/// \param Flags Write flags to use.
233+
///
234+
/// \return Returns the results of the write.
235+
WriteResults writeMaybeRepair(
236+
SmallVectorImpl<char> &Buffer, bool AddHeader,
237+
const WriteFlags &Flags) const;
238+
239+
bool write(SmallVectorImpl<char> &Buffer, bool AddHeader,
240+
const WriteFlags &Flags) const {
241+
return writeMaybeRepair(Buffer, AddHeader, Flags).NumErrors == 0;
242+
}
243+
244+
bool write(SmallVectorImpl<char> &Buffer, bool AddHeader) const {
245+
WriteFlags Flags;
246+
return write(Buffer, AddHeader, Flags);
247+
}
248+
163249
/// \brief The types of editing actions that can be applied.
164250
enum EditAction {
165251
AddBefore, // Insert new record before base record at index.
@@ -190,6 +276,11 @@ class NaClMungedBitcode {
190276
/// set of base records.
191277
void removeEdits();
192278

279+
/// Returns the unedited list of bitcode records.
280+
const NaClBitcodeRecordList &getBaseRecords() const {
281+
return *BaseRecords;
282+
}
283+
193284
private:
194285
typedef std::list<NaClBitcodeAbbrevRecord *> RecordListType;
195286
typedef std::map<size_t, RecordListType *> InsertionsMapType;
@@ -241,7 +332,7 @@ class NaClBitcodeAbbrevRecord : public NaClBitcodeRecordData {
241332
/// \param Code The selector code of the record.
242333
/// \param Values The values associated with the selector code.
243334
NaClBitcodeAbbrevRecord(unsigned Abbrev, unsigned Code,
244-
NaClRecordVector &Values)
335+
const NaClRecordVector &Values)
245336
: NaClBitcodeRecordData(Code, Values), Abbrev(Abbrev) {}
246337

247338
/// \brief Creates a copy of the given abbreviated bitcode record.

include/llvm/Bitcode/NaCl/NaClBitstreamWriter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class NaClBitstreamWriter {
123123
: Out(O), CurBit(0), CurValue(0), CurCodeSize() {}
124124

125125
~NaClBitstreamWriter() {
126-
assert(CurBit == 0 && "Unflused data remaining");
126+
assert(CurBit == 0 && "Unflushed data remaining");
127127
assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance");
128128

129129
// Free the BlockInfoRecords.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
add_llvm_library(LLVMNaClBitTestUtils
22
NaClBitcodeMunge.cpp
3+
NaClBitcodeMungeReader.cpp
34
NaClBitcodeMungeUtils.cpp
5+
NaClBitcodeMungeWriter.cpp
46
)
57
add_dependencies(LLVMNaClBitTestUtils intrinsics_gen)

0 commit comments

Comments
 (0)