LLVM  3.7.0
SymbolRewriter.cpp
Go to the documentation of this file.
1 //===- SymbolRewriter.cpp - Symbol Rewriter ---------------------*- 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 // SymbolRewriter is a LLVM pass which can rewrite symbols transparently within
11 // existing code. It is implemented as a compiler pass and is configured via a
12 // YAML configuration file.
13 //
14 // The YAML configuration file format is as follows:
15 //
16 // RewriteMapFile := RewriteDescriptors
17 // RewriteDescriptors := RewriteDescriptor | RewriteDescriptors
18 // RewriteDescriptor := RewriteDescriptorType ':' '{' RewriteDescriptorFields '}'
19 // RewriteDescriptorFields := RewriteDescriptorField | RewriteDescriptorFields
20 // RewriteDescriptorField := FieldIdentifier ':' FieldValue ','
21 // RewriteDescriptorType := Identifier
22 // FieldIdentifier := Identifier
23 // FieldValue := Identifier
24 // Identifier := [0-9a-zA-Z]+
25 //
26 // Currently, the following descriptor types are supported:
27 //
28 // - function: (function rewriting)
29 // + Source (original name of the function)
30 // + Target (explicit transformation)
31 // + Transform (pattern transformation)
32 // + Naked (boolean, whether the function is undecorated)
33 // - global variable: (external linkage global variable rewriting)
34 // + Source (original name of externally visible variable)
35 // + Target (explicit transformation)
36 // + Transform (pattern transformation)
37 // - global alias: (global alias rewriting)
38 // + Source (original name of the aliased name)
39 // + Target (explicit transformation)
40 // + Transform (pattern transformation)
41 //
42 // Note that source and exactly one of [Target, Transform] must be provided
43 //
44 // New rewrite descriptors can be created. Addding a new rewrite descriptor
45 // involves:
46 //
47 // a) extended the rewrite descriptor kind enumeration
48 // (<anonymous>::RewriteDescriptor::RewriteDescriptorType)
49 // b) implementing the new descriptor
50 // (c.f. <anonymous>::ExplicitRewriteFunctionDescriptor)
51 // c) extending the rewrite map parser
52 // (<anonymous>::RewriteMapParser::parseEntry)
53 //
54 // Specify to rewrite the symbols using the `-rewrite-symbols` option, and
55 // specify the map file to use for the rewriting via the `-rewrite-map-file`
56 // option.
57 //
58 //===----------------------------------------------------------------------===//
59 
60 #define DEBUG_TYPE "symbol-rewriter"
61 #include "llvm/CodeGen/Passes.h"
62 #include "llvm/Pass.h"
63 #include "llvm/ADT/SmallString.h"
66 #include "llvm/Support/Debug.h"
68 #include "llvm/Support/Regex.h"
69 #include "llvm/Support/SourceMgr.h"
74 
75 using namespace llvm;
76 using namespace SymbolRewriter;
77 
78 static cl::list<std::string> RewriteMapFiles("rewrite-map-file",
79  cl::desc("Symbol Rewrite Map"),
80  cl::value_desc("filename"));
81 
82 static void rewriteComdat(Module &M, GlobalObject *GO,
83  const std::string &Source,
84  const std::string &Target) {
85  if (Comdat *CD = GO->getComdat()) {
86  auto &Comdats = M.getComdatSymbolTable();
87 
88  Comdat *C = M.getOrInsertComdat(Target);
89  C->setSelectionKind(CD->getSelectionKind());
90  GO->setComdat(C);
91 
92  Comdats.erase(Comdats.find(Source));
93  }
94 }
95 
96 namespace {
97 template <RewriteDescriptor::Type DT, typename ValueType,
98  ValueType *(llvm::Module::*Get)(StringRef) const>
99 class ExplicitRewriteDescriptor : public RewriteDescriptor {
100 public:
101  const std::string Source;
102  const std::string Target;
103 
104  ExplicitRewriteDescriptor(StringRef S, StringRef T, const bool Naked)
105  : RewriteDescriptor(DT), Source(Naked ? StringRef("\01" + S.str()) : S),
106  Target(T) {}
107 
108  bool performOnModule(Module &M) override;
109 
110  static bool classof(const RewriteDescriptor *RD) {
111  return RD->getType() == DT;
112  }
113 };
114 
115 template <RewriteDescriptor::Type DT, typename ValueType,
116  ValueType *(llvm::Module::*Get)(StringRef) const>
117 bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) {
118  bool Changed = false;
119  if (ValueType *S = (M.*Get)(Source)) {
120  if (GlobalObject *GO = dyn_cast<GlobalObject>(S))
121  rewriteComdat(M, GO, Source, Target);
122 
123  if (Value *T = (M.*Get)(Target))
124  S->setValueName(T->getValueName());
125  else
126  S->setName(Target);
127 
128  Changed = true;
129  }
130  return Changed;
131 }
132 
133 template <RewriteDescriptor::Type DT, typename ValueType,
134  ValueType *(llvm::Module::*Get)(StringRef) const,
135  iterator_range<typename iplist<ValueType>::iterator>
136  (llvm::Module::*Iterator)()>
137 class PatternRewriteDescriptor : public RewriteDescriptor {
138 public:
139  const std::string Pattern;
140  const std::string Transform;
141 
142  PatternRewriteDescriptor(StringRef P, StringRef T)
143  : RewriteDescriptor(DT), Pattern(P), Transform(T) { }
144 
145  bool performOnModule(Module &M) override;
146 
147  static bool classof(const RewriteDescriptor *RD) {
148  return RD->getType() == DT;
149  }
150 };
151 
152 template <RewriteDescriptor::Type DT, typename ValueType,
153  ValueType *(llvm::Module::*Get)(StringRef) const,
154  iterator_range<typename iplist<ValueType>::iterator>
155  (llvm::Module::*Iterator)()>
156 bool PatternRewriteDescriptor<DT, ValueType, Get, Iterator>::
157 performOnModule(Module &M) {
158  bool Changed = false;
159  for (auto &C : (M.*Iterator)()) {
160  std::string Error;
161 
162  std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error);
163  if (!Error.empty())
164  report_fatal_error("unable to transforn " + C.getName() + " in " +
165  M.getModuleIdentifier() + ": " + Error);
166 
167  if (C.getName() == Name)
168  continue;
169 
170  if (GlobalObject *GO = dyn_cast<GlobalObject>(&C))
171  rewriteComdat(M, GO, C.getName(), Name);
172 
173  if (Value *V = (M.*Get)(Name))
174  C.setValueName(V->getValueName());
175  else
176  C.setName(Name);
177 
178  Changed = true;
179  }
180  return Changed;
181 }
182 
183 /// Represents a rewrite for an explicitly named (function) symbol. Both the
184 /// source function name and target function name of the transformation are
185 /// explicitly spelt out.
186 typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::Function,
188  ExplicitRewriteFunctionDescriptor;
189 
190 /// Represents a rewrite for an explicitly named (global variable) symbol. Both
191 /// the source variable name and target variable name are spelt out. This
192 /// applies only to module level variables.
193 typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
196  ExplicitRewriteGlobalVariableDescriptor;
197 
198 /// Represents a rewrite for an explicitly named global alias. Both the source
199 /// and target name are explicitly spelt out.
200 typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::NamedAlias,
203  ExplicitRewriteNamedAliasDescriptor;
204 
205 /// Represents a rewrite for a regular expression based pattern for functions.
206 /// A pattern for the function name is provided and a transformation for that
207 /// pattern to determine the target function name create the rewrite rule.
208 typedef PatternRewriteDescriptor<RewriteDescriptor::Type::Function,
211  PatternRewriteFunctionDescriptor;
212 
213 /// Represents a rewrite for a global variable based upon a matching pattern.
214 /// Each global variable matching the provided pattern will be transformed as
215 /// described in the transformation pattern for the target. Applies only to
216 /// module level variables.
217 typedef PatternRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
218  llvm::GlobalVariable,
221  PatternRewriteGlobalVariableDescriptor;
222 
223 /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global
224 /// aliases which match a given pattern. The provided transformation will be
225 /// applied to each of the matching names.
226 typedef PatternRewriteDescriptor<RewriteDescriptor::Type::NamedAlias,
227  llvm::GlobalAlias,
230  PatternRewriteNamedAliasDescriptor;
231 } // namespace
232 
233 bool RewriteMapParser::parse(const std::string &MapFile,
234  RewriteDescriptorList *DL) {
236  MemoryBuffer::getFile(MapFile);
237 
238  if (!Mapping)
239  report_fatal_error("unable to read rewrite map '" + MapFile + "': " +
240  Mapping.getError().message());
241 
242  if (!parse(*Mapping, DL))
243  report_fatal_error("unable to parse rewrite map '" + MapFile + "'");
244 
245  return true;
246 }
247 
248 bool RewriteMapParser::parse(std::unique_ptr<MemoryBuffer> &MapFile,
249  RewriteDescriptorList *DL) {
250  SourceMgr SM;
251  yaml::Stream YS(MapFile->getBuffer(), SM);
252 
253  for (auto &Document : YS) {
254  yaml::MappingNode *DescriptorList;
255 
256  // ignore empty documents
257  if (isa<yaml::NullNode>(Document.getRoot()))
258  continue;
259 
260  DescriptorList = dyn_cast<yaml::MappingNode>(Document.getRoot());
261  if (!DescriptorList) {
262  YS.printError(Document.getRoot(), "DescriptorList node must be a map");
263  return false;
264  }
265 
266  for (auto &Descriptor : *DescriptorList)
267  if (!parseEntry(YS, Descriptor, DL))
268  return false;
269  }
270 
271  return true;
272 }
273 
274 bool RewriteMapParser::parseEntry(yaml::Stream &YS, yaml::KeyValueNode &Entry,
275  RewriteDescriptorList *DL) {
276  yaml::ScalarNode *Key;
278  SmallString<32> KeyStorage;
279  StringRef RewriteType;
280 
281  Key = dyn_cast<yaml::ScalarNode>(Entry.getKey());
282  if (!Key) {
283  YS.printError(Entry.getKey(), "rewrite type must be a scalar");
284  return false;
285  }
286 
287  Value = dyn_cast<yaml::MappingNode>(Entry.getValue());
288  if (!Value) {
289  YS.printError(Entry.getValue(), "rewrite descriptor must be a map");
290  return false;
291  }
292 
293  RewriteType = Key->getValue(KeyStorage);
294  if (RewriteType.equals("function"))
295  return parseRewriteFunctionDescriptor(YS, Key, Value, DL);
296  else if (RewriteType.equals("global variable"))
297  return parseRewriteGlobalVariableDescriptor(YS, Key, Value, DL);
298  else if (RewriteType.equals("global alias"))
299  return parseRewriteGlobalAliasDescriptor(YS, Key, Value, DL);
300 
301  YS.printError(Entry.getKey(), "unknown rewrite type");
302  return false;
303 }
304 
305 bool RewriteMapParser::
306 parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
307  yaml::MappingNode *Descriptor,
308  RewriteDescriptorList *DL) {
309  bool Naked = false;
310  std::string Source;
311  std::string Target;
312  std::string Transform;
313 
314  for (auto &Field : *Descriptor) {
315  yaml::ScalarNode *Key;
316  yaml::ScalarNode *Value;
317  SmallString<32> KeyStorage;
318  SmallString<32> ValueStorage;
319  StringRef KeyValue;
320 
321  Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
322  if (!Key) {
323  YS.printError(Field.getKey(), "descriptor key must be a scalar");
324  return false;
325  }
326 
327  Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
328  if (!Value) {
329  YS.printError(Field.getValue(), "descriptor value must be a scalar");
330  return false;
331  }
332 
333  KeyValue = Key->getValue(KeyStorage);
334  if (KeyValue.equals("source")) {
335  std::string Error;
336 
337  Source = Value->getValue(ValueStorage);
338  if (!Regex(Source).isValid(Error)) {
339  YS.printError(Field.getKey(), "invalid regex: " + Error);
340  return false;
341  }
342  } else if (KeyValue.equals("target")) {
343  Target = Value->getValue(ValueStorage);
344  } else if (KeyValue.equals("transform")) {
345  Transform = Value->getValue(ValueStorage);
346  } else if (KeyValue.equals("naked")) {
347  std::string Undecorated;
348 
349  Undecorated = Value->getValue(ValueStorage);
350  Naked = StringRef(Undecorated).lower() == "true" || Undecorated == "1";
351  } else {
352  YS.printError(Field.getKey(), "unknown key for function");
353  return false;
354  }
355  }
356 
357  if (Transform.empty() == Target.empty()) {
358  YS.printError(Descriptor,
359  "exactly one of transform or target must be specified");
360  return false;
361  }
362 
363  // TODO see if there is a more elegant solution to selecting the rewrite
364  // descriptor type
365  if (!Target.empty())
366  DL->push_back(new ExplicitRewriteFunctionDescriptor(Source, Target, Naked));
367  else
368  DL->push_back(new PatternRewriteFunctionDescriptor(Source, Transform));
369 
370  return true;
371 }
372 
373 bool RewriteMapParser::
374 parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
375  yaml::MappingNode *Descriptor,
376  RewriteDescriptorList *DL) {
377  std::string Source;
378  std::string Target;
379  std::string Transform;
380 
381  for (auto &Field : *Descriptor) {
382  yaml::ScalarNode *Key;
383  yaml::ScalarNode *Value;
384  SmallString<32> KeyStorage;
385  SmallString<32> ValueStorage;
386  StringRef KeyValue;
387 
388  Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
389  if (!Key) {
390  YS.printError(Field.getKey(), "descriptor Key must be a scalar");
391  return false;
392  }
393 
394  Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
395  if (!Value) {
396  YS.printError(Field.getValue(), "descriptor value must be a scalar");
397  return false;
398  }
399 
400  KeyValue = Key->getValue(KeyStorage);
401  if (KeyValue.equals("source")) {
402  std::string Error;
403 
404  Source = Value->getValue(ValueStorage);
405  if (!Regex(Source).isValid(Error)) {
406  YS.printError(Field.getKey(), "invalid regex: " + Error);
407  return false;
408  }
409  } else if (KeyValue.equals("target")) {
410  Target = Value->getValue(ValueStorage);
411  } else if (KeyValue.equals("transform")) {
412  Transform = Value->getValue(ValueStorage);
413  } else {
414  YS.printError(Field.getKey(), "unknown Key for Global Variable");
415  return false;
416  }
417  }
418 
419  if (Transform.empty() == Target.empty()) {
420  YS.printError(Descriptor,
421  "exactly one of transform or target must be specified");
422  return false;
423  }
424 
425  if (!Target.empty())
426  DL->push_back(new ExplicitRewriteGlobalVariableDescriptor(Source, Target,
427  /*Naked*/false));
428  else
429  DL->push_back(new PatternRewriteGlobalVariableDescriptor(Source,
430  Transform));
431 
432  return true;
433 }
434 
435 bool RewriteMapParser::
436 parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
437  yaml::MappingNode *Descriptor,
438  RewriteDescriptorList *DL) {
439  std::string Source;
440  std::string Target;
441  std::string Transform;
442 
443  for (auto &Field : *Descriptor) {
444  yaml::ScalarNode *Key;
445  yaml::ScalarNode *Value;
446  SmallString<32> KeyStorage;
447  SmallString<32> ValueStorage;
448  StringRef KeyValue;
449 
450  Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
451  if (!Key) {
452  YS.printError(Field.getKey(), "descriptor key must be a scalar");
453  return false;
454  }
455 
456  Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
457  if (!Value) {
458  YS.printError(Field.getValue(), "descriptor value must be a scalar");
459  return false;
460  }
461 
462  KeyValue = Key->getValue(KeyStorage);
463  if (KeyValue.equals("source")) {
464  std::string Error;
465 
466  Source = Value->getValue(ValueStorage);
467  if (!Regex(Source).isValid(Error)) {
468  YS.printError(Field.getKey(), "invalid regex: " + Error);
469  return false;
470  }
471  } else if (KeyValue.equals("target")) {
472  Target = Value->getValue(ValueStorage);
473  } else if (KeyValue.equals("transform")) {
474  Transform = Value->getValue(ValueStorage);
475  } else {
476  YS.printError(Field.getKey(), "unknown key for Global Alias");
477  return false;
478  }
479  }
480 
481  if (Transform.empty() == Target.empty()) {
482  YS.printError(Descriptor,
483  "exactly one of transform or target must be specified");
484  return false;
485  }
486 
487  if (!Target.empty())
488  DL->push_back(new ExplicitRewriteNamedAliasDescriptor(Source, Target,
489  /*Naked*/false));
490  else
491  DL->push_back(new PatternRewriteNamedAliasDescriptor(Source, Transform));
492 
493  return true;
494 }
495 
496 namespace {
497 class RewriteSymbols : public ModulePass {
498 public:
499  static char ID; // Pass identification, replacement for typeid
500 
501  RewriteSymbols();
502  RewriteSymbols(SymbolRewriter::RewriteDescriptorList &DL);
503 
504  bool runOnModule(Module &M) override;
505 
506 private:
507  void loadAndParseMapFiles();
508 
510 };
511 
512 char RewriteSymbols::ID = 0;
513 
514 RewriteSymbols::RewriteSymbols() : ModulePass(ID) {
516  loadAndParseMapFiles();
517 }
518 
519 RewriteSymbols::RewriteSymbols(SymbolRewriter::RewriteDescriptorList &DL)
520  : ModulePass(ID) {
521  Descriptors.splice(Descriptors.begin(), DL);
522 }
523 
524 bool RewriteSymbols::runOnModule(Module &M) {
525  bool Changed;
526 
527  Changed = false;
528  for (auto &Descriptor : Descriptors)
529  Changed |= Descriptor.performOnModule(M);
530 
531  return Changed;
532 }
533 
534 void RewriteSymbols::loadAndParseMapFiles() {
535  const std::vector<std::string> MapFiles(RewriteMapFiles);
537 
538  for (const auto &MapFile : MapFiles)
539  parser.parse(MapFile, &Descriptors);
540 }
541 }
542 
543 INITIALIZE_PASS(RewriteSymbols, "rewrite-symbols", "Rewrite Symbols", false,
544  false)
545 
546 ModulePass *llvm::createRewriteSymbolsPass() { return new RewriteSymbols(); }
547 
548 ModulePass *
550  return new RewriteSymbols(DL);
551 }
std::error_code getError() const
Definition: ErrorOr.h:178
Represents either an error or a value T.
Definition: ErrorOr.h:82
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:114
StringRef getValue(SmallVectorImpl< char > &Storage) const
Gets the value of this node as a StringRef.
function - descriptor rewrites a function
Node * getKey()
Parse and return the key.
static cl::list< std::string > RewriteMapFiles("rewrite-map-file", cl::desc("Symbol Rewrite Map"), cl::value_desc("filename"))
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Reports a serious error, calling any installed error handler.
void push_back(NodeTy *val)
Definition: ilist.h:554
The basic entity representing a rewrite operation.
bool parse(const std::string &MapFile, RewriteDescriptorList *Descriptors)
A key and value pair.
Definition: YAMLParser.h:263
void setComdat(Comdat *C)
Definition: GlobalObject.h:63
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:25
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
Definition: Module.cpp:188
#define P(N)
iterator_range< iterator > functions()
Definition: Module.h:580
void printError(Node *N, const Twine &Msg)
const Comdat * getComdat() const
Definition: GlobalObject.h:61
INITIALIZE_PASS(RewriteSymbols,"rewrite-symbols","Rewrite Symbols", false, false) ModulePass *llvm
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling...
Definition: SourceMgr.h:35
Comdat * getOrInsertComdat(StringRef Name)
Return the Comdat in the module with the specified name.
Definition: Module.cpp:465
std::string sub(StringRef Repl, StringRef String, std::string *Error=nullptr)
sub - Return the result of replacing the first match of the regex in String with the Repl string...
Definition: Regex.cpp:98
iplist - The subset of list functionality that can safely be used on nodes of polymorphic types...
Definition: ilist.h:49
A scalar node is an opaque datum that can be presented as a series of zero or more Unicode scalar val...
Definition: YAMLParser.h:190
Node * getValue()
Parse and return the value.
void setSelectionKind(SelectionKind Val)
Definition: Comdat.h:43
global variable - descriptor rewrites a global variable
This class represents a YAML stream potentially containing multiple documents.
Definition: YAMLParser.h:76
ModulePass * createRewriteSymbolsPass()
A range adaptor for a pair of iterators.
Target - Wrapper for Target specific information.
GlobalAlias * getNamedAlias(StringRef Name) const
Return the global alias in the module with the specified name, of arbitrary type. ...
Definition: Module.cpp:246
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:285
bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
Definition: StringRef.h:136
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatileSize=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
const ComdatSymTabType & getComdatSymbolTable() const
Get the Module's symbol table for COMDATs (constant).
Definition: Module.h:544
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:236
Represents a YAML map created from either a block map for a flow map.
Definition: YAMLParser.h:374
aarch64 promote const
LLVM Value Representation.
Definition: Value.h:69
iterator_range< global_iterator > globals()
Definition: Module.h:558
C - The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
static void rewriteComdat(Module &M, GlobalObject *GO, const std::string &Source, const std::string &Target)
std::string lower() const
Definition: StringRef.cpp:117
void initializeRewriteSymbolsPass(PassRegistry &)
GlobalVariable * getGlobalVariable(StringRef Name) const
Look up the specified global variable in the module symbol table.
Definition: Module.h:381
iterator_range< alias_iterator > aliases()
Definition: Module.h:598