Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h

Issue 1960393002: Subzero: Add necessary PNaCl files for standalone build. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //===- NaClBitcodeMungeUtils.h - Munge bitcode records --------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines utility class NaClMungedBitcode to edit a base
11 // sequence of PNaCl bitcode records. It is intended to be used for
12 // both unit testing, and for fuzzing bitcode files.
13 //
14 // The editing actions are defined in terms of the base sequence of
15 // bitcode records, and do not actually modify that base sequence. As
16 // such, all edits are defined relative to a record index in the base
17 // sequence of bitcode records. Using record indices into the base
18 // sequence means that succeeding edits need not modify record indices
19 // based on the effects of preceding edits. Rather, the record index
20 // remains constant across all editing actions.
21 //
22 // There are two steps in creating munged bitcode. The first step
23 // defines the initial (base) sequence of bitcode records to be
24 // edited. The second is to apply editing actions to the base sequence
25 // of records.
26 //
27 // Defining the initial sequence of bitcode records is done by
28 // using NaClMungedBitcode's constructor.
29 //
30 // There are four kinds of editing actions:
31 //
32 // 1) Add a record before a (base) record index.
33 // 2) Add a record after a (base) record index.
34 // 3) Remove a record at a (base) record index.
35 // 4) Replace a record at a (base) record index.
36 //
37 // Each of the editing actions are defined by the methods addBefore(),
38 // addAfter(), remove(), and replace(). The edited sequence of records
39 // is defined by an iterator, and is accessible using methods begin()
40 // and end().
41 //
42 // If multiple records are added before/after a record index, the
43 // order of the added records correspond to the order they were added.
44 //
45 // For unit testing, simple array interfaces are provided. The first
46 // interface defines the initial base sequence of bitcode records. The
47 // second interface, method munge(), defines a sequence of editing
48 // actions to apply to the base sequence of records.
49 //
50 // These arrays are defined using type uint64_t. A bitcode record is
51 // defined as a sequence of values of the form:
52 //
53 // AbbrevIndex, RecordCode, Value1, ..., ValueN , Terminator
54 //
55 // Terminator is a (user-specified) designated constant used to mark
56 // the end of bitcode records. A record can contain zero or more
57 // values.
58 //
59 // An editing action is defined as one of the following sequences of
60 // values:
61 //
62 // RecordIndex, AddBefore, AbbrevIndex, RecordCode, Value, ..., Terminator
63 // RecordIndex, AddAfter, AbbrevIndex, RecordCode, Value, ..., Terminator
64 // RecordIndex, Remove
65 // RecordIndex, Replace, AbbrevIndex, RecordCode, Value, ..., Terminator.
66 //
67 // RecordIndex defines where the action applies, relative to the base
68 // sequence of records. EditAction defines the editing action to
69 // apply. The remaining fields define an optional record associated
70 // with the editing action.
71 //
72 // ===---------------------------------------------------------------------===//
Karl 2016/05/10 14:49:48 Is this file really needed? It is only used in a
Jim Stichnoth 2016/05/10 18:11:48 Done.
73
74 #ifndef LLVM_BITCODE_NACL_NACLBITCODEMUNGEUTILS_H
75 #define LLVM_BITCODE_NACL_NACLBITCODEMUNGEUTILS_H
76
77 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
78 #include "llvm/Support/MemoryBuffer.h"
79
80 #include <list>
81 #include <map>
82
83 namespace llvm {
84
85 class NaClBitcodeAbbrevRecord; // bitcode record.
86 class NaClMungedBitcodeIter; // iterator over edited bitcode records.
87
88 /// \brief Defines a list of bitcode records.
89 typedef std::vector<std::unique_ptr<NaClBitcodeAbbrevRecord>>
90 NaClBitcodeRecordList;
91
92 // TODO(kschimpf): Modify following two methods to return error_code.
93
94 /// \brief Extracts out the records in Records, and puts them into RecordList.
95 ///
96 /// \brief RecordList[in/out] Record list to read into.
97 /// \brief Records Array containing data defining records.
98 /// \brief RecordsSize The size of array Records.
99 /// \brief RecordTerminator The value used to terminate records.
100 void readNaClBitcodeRecordList(NaClBitcodeRecordList &RecordList,
101 const uint64_t Records[],
102 size_t RecordsSize,
103 uint64_t RecordTerminator);
104
105 /// Read in the list of records from binary bitcode from a memory buffer.
106 void readNaClBitcodeRecordList(NaClBitcodeRecordList &RecordList,
107 std::unique_ptr<MemoryBuffer> InputBuffer);
108
109 /// Read in the list of records from textual bitcode from a memory buffer.
110 std::error_code readNaClTextBcRecordList(
111 NaClBitcodeRecordList &RecordList,
112 std::unique_ptr<MemoryBuffer> InputBuffer);
113
114 /// Read textual bitcode records from Filename, and fill Buffer with
115 /// corresponding bitcode. Return error_code describing success of
116 /// read. Verbose (if not nullptr) is used to generate more human
117 /// readable error messages than the text in the returned error
118 /// message.
119 std::error_code readNaClRecordTextAndBuildBitcode(
120 StringRef Filename, SmallVectorImpl<char> &Buffer,
121 raw_ostream *Verbose = nullptr);
122
123 /// Write out RecordList (as text) to Buffer. Returns true when
124 /// successful. Error message are written to ErrStream.
125 bool writeNaClBitcodeRecordList(NaClBitcodeRecordList &RecordList,
126 SmallVectorImpl<char> &Buffer,
127 raw_ostream &ErrStream);
128
129 /// \brief An edited (i.e. munged) list of bitcode records. Edits are
130 /// always relative to the initial list of records.
131 class NaClMungedBitcode {
132 friend class NaClMungedBitcodeIter;
133 NaClMungedBitcode() = delete;
134 NaClMungedBitcode(const NaClMungedBitcode &) = delete;
135 NaClMungedBitcode &operator=(const NaClMungedBitcode &) = delete;
136
137 public:
138 /// \brief Iterator over edited records.
139 typedef NaClMungedBitcodeIter iterator;
140
141 /// \brief Read in initial list of records from bitcode in a memory buffer.
142 explicit NaClMungedBitcode(std::unique_ptr<MemoryBuffer> InputBuffer,
143 bool ReadAsText=false)
144 : BaseRecords(new NaClBitcodeRecordList()) {
145 if (ReadAsText)
146 readNaClTextBcRecordList(*BaseRecords, std::move(InputBuffer));
147 else
148 readNaClBitcodeRecordList(*BaseRecords, std::move(InputBuffer));
149 }
150
151 /// \brief Initialize the list of records to be edited.
152 explicit NaClMungedBitcode(std::unique_ptr<NaClBitcodeRecordList> BaseRecords)
153 : BaseRecords(std::move(BaseRecords)) {}
154
155 /// \brief Initialize the list of records to be edited using
156 /// array specification.
157 ///
158 /// \brief Records Array containing data defining records.
159 /// \brief RecordsSize The size of array Records.
160 /// \brief RecordTerminator The value used to terminate records.
161 NaClMungedBitcode(const uint64_t Records[], size_t RecordsSize,
162 uint64_t RecordTerminator);
163
164 ~NaClMungedBitcode();
165
166 /// \brief Iterator pointing to first record in edited records.
167 NaClMungedBitcodeIter begin() const;
168
169 /// \brief Iterator pointing after last record in edited records.
170 NaClMungedBitcodeIter end() const;
171
172 /// \brief Insert Record immediately before the record at RecordIndex.
173 ///
174 /// \param RecordIndex The index (within BaseRecords) to add before.
175 /// \param Record The record to add.
176 void addBefore(size_t RecordIndex, NaClBitcodeAbbrevRecord &Record);
177
178 /// \brief Insert Record after the record at RecordIndex (and after
179 /// any previously added after records for RecordIndex).
180 ///
181 /// \param RecordIndex The index (within BaseRecords) to add after.
182 /// \param Record The record to add.
183 void addAfter(size_t RecordIndex, NaClBitcodeAbbrevRecord &Record);
184
185 /// \brief Remove the record at RecordIndex. Note that because
186 /// the record index is based on the base records, and those records
187 /// are not modified, this editing action effectively undoes all
188 /// previous remove/replace editing actions for this index.
189 void remove(size_t RecordIndex);
190
191 /// \brief Replace the record at RecordIndex with Record. Note that
192 /// because the record index is based on the base records, and those
193 /// records are not modified, this editing action effectively undoes
194 /// all previous remove/replace editing actions for this index.
195 void replace(size_t RecordIndex, NaClBitcodeAbbrevRecord &Record);
196
197 /// \brief Print out the resulting edited list of records.
198 void print(raw_ostream &Out) const;
199
200 /// Defines set of possible write flags.
201 struct WriteFlags {
202 /// True if error recovery should be applied.
203 bool getTryToRecover() const { return TryToRecover; }
204
205 /// Define that error recovery should be applied when writing.
206 void setTryToRecover(bool NewValue) {
207 TryToRecover = NewValue;
208 assert(!(TryToRecover && WriteBadAbbrevIndex));
209 }
210
211 /// True if a bad abbreviation index should be written (rather than
212 /// trying error recovery) so that bitcode readers can be tested for
213 /// this condition.
214 bool getWriteBadAbbrevIndex() const { return WriteBadAbbrevIndex; }
215
216 /// Define that the first bad abbreviation index should be written,
217 /// and corresponding minimal context added so that the bitcode can
218 /// be used to test reading the erroneous written bitcode.
219 void setWriteBadAbbrevIndex(bool NewValue) {
220 WriteBadAbbrevIndex = NewValue;
221 assert(!(TryToRecover && WriteBadAbbrevIndex));
222 }
223
224 /// Get the stream to print errors while writing bitcode.
225 raw_ostream &getErrStream() const {
226 return ErrStream ? *ErrStream : errs();
227 }
228
229 /// Set the stream to print errors to.
230 void setErrStream(raw_ostream &NewValue) {
231 ErrStream = &NewValue;
232 }
233
234 void reset() {
235 TryToRecover = false;
236 WriteBadAbbrevIndex = false;
237 ErrStream = nullptr;
238 }
239
240 private:
241 bool TryToRecover = false;
242 bool WriteBadAbbrevIndex = false;
243 raw_ostream *ErrStream = nullptr;
244 };
245
246 /// Defines the results associated with writing bitcode.
247 struct WriteResults {
248 /// Number of errors generated.
249 size_t NumErrors = 0;
250 /// Number of repairs (via error recovery) that were applied.
251 size_t NumRepairs = 0;
252 /// True if a bad abbreviation index were written.
253 bool WroteBadAbbrevIndex = false;
254 };
255
256 /// \brief Write out the edited list of bitcode records using
257 /// the given buffer.
258 ///
259 /// \param Buffer The buffer to write into.
260 /// \param AddHeader Add header block when true.
261 /// \param Flags Write flags to use.
262 ///
263 /// \return Returns the results of the write.
264 WriteResults writeMaybeRepair(
265 SmallVectorImpl<char> &Buffer, bool AddHeader,
266 const WriteFlags &Flags) const;
267
268 bool write(SmallVectorImpl<char> &Buffer, bool AddHeader,
269 const WriteFlags &Flags) const {
270 WriteResults Results = writeMaybeRepair(Buffer, AddHeader, Flags);
271 return Results.NumErrors == 0
272 || (Flags.getTryToRecover() && Results.NumErrors == Results.NumRepairs);
273 }
274
275 bool write(SmallVectorImpl<char> &Buffer, bool AddHeader) const {
276 WriteFlags Flags;
277 return write(Buffer, AddHeader, Flags);
278 }
279
280 /// \brief The types of editing actions that can be applied.
281 enum EditAction {
282 AddBefore, // Insert new record before base record at index.
283 AddAfter, // Insert new record after base record at index.
284 Remove, // Remove record at index.
285 Replace // Replace base record at index with new record.
286 };
287
288 /// \brief Apply a set of edits defined in the given array.
289 ///
290 /// Actions are a sequence of values, followed by a (common)
291 /// terminator value. Valid action sequences are:
292 ///
293 /// RecordIndex AddBefore Abbrev Code Values Terminator
294 ///
295 /// RecordIndex AddAfter Abbrev Code Values Terminator
296 ///
297 /// RecordIndex Remove
298 ///
299 /// RecordIndex Replace Abbrev Code Values Terminator
300 ///
301 /// \param Munges The array containing the edits to apply.
302 /// \param MungesSize The size of Munges.
303 /// \param Terminator The value used to terminate records in editing actions.
304 void munge(const uint64_t Munges[], size_t MungesSize, uint64_t Terminator);
305
306 /// \brief Removes all editing actions and resets back to the original
307 /// set of base records.
308 void removeEdits();
309
310 /// Returns the unedited list of bitcode records.
311 const NaClBitcodeRecordList &getBaseRecords() const {
312 return *BaseRecords;
313 }
314
315 private:
316 typedef std::list<NaClBitcodeAbbrevRecord *> RecordListType;
317 typedef std::map<size_t, RecordListType *> InsertionsMapType;
318 typedef std::map<size_t, NaClBitcodeAbbrevRecord *> ReplaceMapType;
319
320 /// \brief The list of base records that will be edited.
321 std::unique_ptr<NaClBitcodeRecordList> BaseRecords;
322 // Holds map from record index to list of records added before
323 // the corresponding record in the list of base records.
324 InsertionsMapType BeforeInsertionsMap;
325 // Holds map from record index to the list of records added after
326 // the corresponding record in the list of base records.
327 InsertionsMapType AfterInsertionsMap;
328 // Holds map from record index to the record that replaces the
329 // corresponding record in the list of base records. Note: If the
330 // range is the nullptr, it corresponds to a remove instead of a
331 // replace.
332 ReplaceMapType ReplaceMap;
333
334 // Returns the list of records associated with Index in Map.
335 RecordListType &at(InsertionsMapType &Map, size_t Index) {
336 InsertionsMapType::iterator Pos = Map.find(Index);
337 if (Pos == Map.end()) {
338 RecordListType *List = new RecordListType();
339 Map.emplace(Index, List);
340 return *List;
341 }
342 return *Pos->second;
343 }
344
345 // Creates a (heap allocated) copy of the given record.
346 NaClBitcodeAbbrevRecord *copy(const NaClBitcodeAbbrevRecord &Record);
347
348 // Delete nested objects within insertions map.
349 void destroyInsertionsMap(NaClMungedBitcode::InsertionsMapType &Map);
350 };
351
352 /// \brief Defines a bitcode record with its associated abbreviation index.
353 class NaClBitcodeAbbrevRecord : public NaClBitcodeRecordData {
354 NaClBitcodeAbbrevRecord &operator=(NaClBitcodeAbbrevRecord &) = delete;
355
356 public:
357 /// \brief The abbreviation associated with the bitcode record.
358 unsigned Abbrev;
359
360 /// \brief Creates a bitcode record.
361 ///
362 /// \param Abbrev Abbreviation index associated with record.
363 /// \param Code The selector code of the record.
364 /// \param Values The values associated with the selector code.
365 NaClBitcodeAbbrevRecord(unsigned Abbrev, unsigned Code,
366 const NaClRecordVector &Values)
367 : NaClBitcodeRecordData(Code, Values), Abbrev(Abbrev) {}
368
369 /// \brief Creates a copy of the given abbreviated bitcode record.
370 explicit NaClBitcodeAbbrevRecord(const NaClBitcodeAbbrevRecord &Rcd)
371 : NaClBitcodeRecordData(Rcd), Abbrev(Rcd.Abbrev) {}
372
373 /// \brief Creates a default abbreviated bitcode record.
374 NaClBitcodeAbbrevRecord() : Abbrev(naclbitc::UNABBREV_RECORD) {}
375
376 ~NaClBitcodeAbbrevRecord() {}
377
378 /// \brief Replaces the contents of the abbreviated bitcode record with
379 /// the corresponding contents in the array.
380 ///
381 /// \param Values The array to get values from.
382 /// \param ValuesSize The length of the Values array.
383 /// \param Terminator The value defining the end of the record in Values.
384 /// \param Index The index of the first value to be used in Values.
385 void read(const uint64_t Values[], size_t ValuesSize,
386 const uint64_t Terminator, size_t &Index);
387
388 void print(raw_ostream &out) const;
389 };
390
391 inline raw_ostream &operator<<(raw_ostream &Out,
392 const NaClBitcodeAbbrevRecord &Record) {
393 Record.print(Out);
394 return Out;
395 }
396
397 /// \brief Defines an iterator to walk over elements of an edited
398 /// record list.
399 class NaClMungedBitcodeIter {
400
401 public:
402 /// \brief Returns an iterator pointing to the first record in the
403 /// edited list of records.
404 static NaClMungedBitcodeIter begin(const NaClMungedBitcode &MungedBitcode) {
405 return NaClMungedBitcodeIter(MungedBitcode, 0);
406 }
407
408 /// \brief Returns an iterator pointing past the last record in the
409 /// edited list of records.
410 static NaClMungedBitcodeIter end(const NaClMungedBitcode &MungedBitcode) {
411 return NaClMungedBitcodeIter(MungedBitcode,
412 MungedBitcode.BaseRecords->size());
413 }
414
415 bool operator==(const NaClMungedBitcodeIter &Iter) const;
416
417 bool operator!=(const NaClMungedBitcodeIter &Iter) const {
418 return !operator==(Iter);
419 }
420
421 /// \brief Advances the iterator over one record in the list of
422 /// edited records.
423 NaClMungedBitcodeIter &operator++();
424
425 /// \brief Returns the bitcode record the iterator is before.
426 NaClBitcodeAbbrevRecord &operator*();
427
428 private:
429 /// \brief Defines position of the iterator, relative to the corresponding
430 /// record index in the base list of records.
431 enum MungedPosition {
432 /// Processing the list of records inserted before the record
433 /// index of the base list of records.
434 InBeforeInsertions,
435 /// Processing the record at the given record index of the base
436 /// list of records.
437 AtIndex,
438 /// Processing the list of records inserted after the record index
439 /// of the base list of records.
440 InAfterInsertions,
441 };
442
443 // The edited list of records to iterate over.
444 const NaClMungedBitcode *MungedBitcode;
445 // The corresponding index, wrt to the edited list of records, that
446 // is being processed.
447 size_t Index;
448 // The position of the iterator wrt to Index.
449 MungedPosition Position;
450 // An iterator defining the current position within a
451 // BeforeInsertions or AfterInsertions list. When the iterator is
452 // not in the corresponding position (i.e. InBeforeInsertions or
453 // InAfterInsertions) this iterator is undefined.
454 NaClMungedBitcode::RecordListType::const_iterator InsertionsIter;
455 // An iterator defining the end position of the corresponding list
456 // of records defined by InsertionsIter. Only defined when
457 // InsertionsIter is defined.
458 NaClMungedBitcode::RecordListType::const_iterator InsertionsIterEnd;
459 // Dummy list to initialize InsertionsIter if no such list exists.
460 NaClMungedBitcode::RecordListType EmptyList;
461
462 // \brief Defines an iterator at the beginning of the
463 // BeforeInsertions list associated with the given Index in
464 // MungedBitcode.
465 NaClMungedBitcodeIter(const NaClMungedBitcode &MungedBitcode, size_t Index)
466 : MungedBitcode(&MungedBitcode), Index(Index),
467 Position(InBeforeInsertions), InsertionsIter(), InsertionsIterEnd() {
468 placeAt(MungedBitcode.BeforeInsertionsMap, 0);
469 updatePosition();
470 }
471
472 // \brief Places the corresponding insertions iterator based on the
473 // list of records defined at Index for the given insertions Map.
474 void placeAt(const NaClMungedBitcode::InsertionsMapType &Map, size_t Index) {
475 NaClMungedBitcode::InsertionsMapType::const_iterator Pos = Map.find(Index);
476 if (Pos == Map.end()) {
477 InsertionsIter = EmptyList.end();
478 InsertionsIterEnd = EmptyList.end();
479 } else {
480 InsertionsIter = Pos->second->begin();
481 InsertionsIterEnd = Pos->second->end();
482 }
483 }
484
485 // \brief Moves the iterator to the position of the next edited
486 // record.
487 void updatePosition();
488 };
489
490 } // end namespace llvm.
491
492 #endif // LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H
OLDNEW
« no previous file with comments | « pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h ('k') | pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeParser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698