Computer Laboratory

Manifest.cpp
Go to the documentation of this file.
1 
2 /*
3  * Copyright (c) 2012-2013 Jonathan Anderson
4  * All rights reserved.
5  *
6  * This software was developed by SRI International and the University of
7  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
8  * ("CTSRD"), as part of the DARPA CRASH research programme.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include "tesla.pb.h"
33 
34 #include "Debug.h"
35 #include "Manifest.h"
36 #include "Names.h"
37 
38 #include "llvm/IR/Function.h"
39 #include "llvm/IR/Instructions.h"
40 #include "llvm/IR/LLVMContext.h"
41 #include "llvm/IR/Module.h"
42 
43 #include "llvm/Support/CommandLine.h"
44 #include "llvm/Support/MemoryBuffer.h"
45 #include "llvm/Support/SourceMgr.h"
46 #include "llvm/Support/raw_ostream.h"
47 #include "llvm/Support/system_error.h"
48 
49 #include <google/protobuf/text_format.h>
50 
51 using namespace llvm;
52 
53 using std::map;
54 using std::string;
55 using std::vector;
56 
57 namespace tesla {
58 
59 cl::opt<string> ManifestName("tesla-manifest", cl::init(".tesla"), cl::Hidden,
60  cl::desc("Name of TESLA manifest file"));
61 
62 const string Manifest::SEP = "===\n";
63 
64 
65 Manifest::~Manifest() {
66  for (auto i : Automata)
67  delete i.second;
68 }
69 
70 const Automaton* Manifest::FindAutomaton(const Identifier& ID) const {
71  auto i = Automata.find(ID);
72  if (i == Automata.end())
73  panic("TESLA manifest does not contain assertion " + ShortName(ID));
74 
75  return i->second;
76 }
77 
78 const Automaton* Manifest::FindAutomaton(const Location& Loc) const {
79  Identifier ID;
80  *ID.mutable_location() = Loc;
81 
82  return FindAutomaton(ID);
83 }
84 
85 
86 Manifest*
87 Manifest::load(raw_ostream& ErrorStream, Automaton::Type T, StringRef Path) {
88  llvm::SourceMgr SM;
89  OwningPtr<MemoryBuffer> Buffer;
90 
91  error_code Error = MemoryBuffer::getFile(Path, Buffer);
92  if (Error != 0) {
93  ErrorStream
94  << "Failed to open TESLA analysis file '" << Path << "': "
95  << Error.message() << "\n"
96  ;
97 
98  return NULL;
99  }
100 
101  OwningPtr<ManifestFile> Protobuf(new ManifestFile);
102  if (!::google::protobuf::TextFormat::ParseFromString(Buffer->getBuffer(),
103  Protobuf.get())) {
104  ErrorStream << "Error parsing TESLA manifest '" << Path << "'\n";
105  return NULL;
106  }
107 
108  AutomataMap Descriptions;
109  map<Identifier,const Automaton*> Automata;
110 
111  // Note the top-level automata that are explicitly named as roots.
112  ArrayRef<const Usage*> Roots(Protobuf->root().data(), Protobuf->root_size());
113  map<Identifier,const Usage*> Uses;
114  for (auto *U : Roots)
115  Uses[U->identifier()] = U;
116 
117  for (auto& A : Protobuf->automaton())
118  Descriptions[A.identifier()] = &A;
119 
120  int id = 0;
121  for (auto i : Descriptions) {
122  const Identifier& ID = i.first;
123  const AutomatonDescription *Descrip = i.second;
124 
125  OwningPtr<NFA> N(NFA::Parse(Descrip, Uses[ID], id++));
126  if (!N) {
127  for (auto i : Automata) delete i.second;
128  for (auto i : Descriptions) delete i.second;
129  return NULL;
130  }
131 
132  OwningPtr<Automaton> Result;
133 
134  if (T == Automaton::Unlinked)
135  Result.reset(N.take());
136 
137  else {
138  N.reset(N->Link(Descriptions));
139 
140  if (T == Automaton::Linked)
141  Result.reset(N.take());
142 
143  else
144  Result.reset(DFA::Convert(N.get()));
145  }
146 
147  Automata[ID] = Result.take();
148  }
149 
150  return new Manifest(Protobuf, Descriptions, Automata, Roots);
151 }
152 
153 StringRef Manifest::defaultLocation() { return ManifestName; }
154 
155 } // namespace tesla
156