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/IR/LegacyPassManager.h" 64 #include "llvm/Support/CommandLine.h" 65 #include "llvm/Support/Debug.h" 66 #include "llvm/Support/MemoryBuffer.h" 67 #include "llvm/Support/Regex.h" 68 #include "llvm/Support/SourceMgr.h" 69 #include "llvm/Support/YAMLParser.h" 70 #include "llvm/Support/raw_ostream.h" 71 #include "llvm/Transforms/IPO/PassManagerBuilder.h" 72 #include "llvm/Transforms/Utils/SymbolRewriter.h" 73 74 using namespace llvm; 75 76 static cl::list<std::string> RewriteMapFiles("rewrite-map-file", 77 cl::desc("Symbol Rewrite Map"), 78 cl::value_desc("filename")); 79 80 namespace llvm { 81 namespace SymbolRewriter { 82 void rewriteComdat(Module &M, GlobalObject *GO, const std::string &Source, 83 const std::string &Target) { 84 if (Comdat *CD = GO->getComdat()) { 85 auto &Comdats = M.getComdatSymbolTable(); 86 87 Comdat *C = M.getOrInsertComdat(Target); 88 C->setSelectionKind(CD->getSelectionKind()); 89 GO->setComdat(C); 90 91 Comdats.erase(Comdats.find(Source)); 92 } 93 } 94 95 template <RewriteDescriptor::Type DT, typename ValueType, 96 ValueType *(llvm::Module::*Get)(StringRef) const> 97 class ExplicitRewriteDescriptor : public RewriteDescriptor { 98 public: 99 const std::string Source; 100 const std::string Target; 101 102 ExplicitRewriteDescriptor(StringRef S, StringRef T, const bool Naked) 103 : RewriteDescriptor(DT), Source(Naked ? StringRef("\01" + S.str()) : S), 104 Target(T) {} 105 106 bool performOnModule(Module &M) override; 107 108 static bool classof(const RewriteDescriptor *RD) { 109 return RD->getType() == DT; 110 } 111 }; 112 113 template <RewriteDescriptor::Type DT, typename ValueType, 114 ValueType *(llvm::Module::*Get)(StringRef) const> 115 bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) { 116 bool Changed = false; 117 if (ValueType *S = (M.*Get)(Source)) { 118 if (GlobalObject *GO = dyn_cast<GlobalObject>(S)) 119 rewriteComdat(M, GO, Source, Target); 120 121 if (Value *T = (M.*Get)(Target)) 122 S->setValueName(T->getValueName()); 123 else 124 S->setName(Target); 125 126 Changed = true; 127 } 128 return Changed; 129 } 130 131 template <RewriteDescriptor::Type DT, typename ValueType, 132 ValueType *(llvm::Module::*Get)(StringRef) const, 133 iterator_range<typename iplist<ValueType>::iterator> 134 (llvm::Module::*Iterator)()> 135 class PatternRewriteDescriptor : public RewriteDescriptor { 136 public: 137 const std::string Pattern; 138 const std::string Transform; 139 140 PatternRewriteDescriptor(StringRef P, StringRef T) 141 : RewriteDescriptor(DT), Pattern(P), Transform(T) { } 142 143 bool performOnModule(Module &M) override; 144 145 static bool classof(const RewriteDescriptor *RD) { 146 return RD->getType() == DT; 147 } 148 }; 149 150 template <RewriteDescriptor::Type DT, typename ValueType, 151 ValueType *(llvm::Module::*Get)(StringRef) const, 152 iterator_range<typename iplist<ValueType>::iterator> 153 (llvm::Module::*Iterator)()> 154 bool PatternRewriteDescriptor<DT, ValueType, Get, Iterator>:: 155 performOnModule(Module &M) { 156 bool Changed = false; 157 for (auto &C : (M.*Iterator)()) { 158 std::string Error; 159 160 std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error); 161 if (!Error.empty()) 162 report_fatal_error("unable to transforn " + C.getName() + " in " + 163 M.getModuleIdentifier() + ": " + Error); 164 165 if (C.getName() == Name) 166 continue; 167 168 if (GlobalObject *GO = dyn_cast<GlobalObject>(&C)) 169 rewriteComdat(M, GO, C.getName(), Name); 170 171 if (Value *V = (M.*Get)(Name)) 172 C.setValueName(V->getValueName()); 173 else 174 C.setName(Name); 175 176 Changed = true; 177 } 178 return Changed; 179 } 180 181 /// Represents a rewrite for an explicitly named (function) symbol. Both the 182 /// source function name and target function name of the transformation are 183 /// explicitly spelt out. 184 typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::Function, 185 llvm::Function, &llvm::Module::getFunction> 186 ExplicitRewriteFunctionDescriptor; 187 188 /// Represents a rewrite for an explicitly named (global variable) symbol. Both 189 /// the source variable name and target variable name are spelt out. This 190 /// applies only to module level variables. 191 typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable, 192 llvm::GlobalVariable, 193 &llvm::Module::getGlobalVariable> 194 ExplicitRewriteGlobalVariableDescriptor; 195 196 /// Represents a rewrite for an explicitly named global alias. Both the source 197 /// and target name are explicitly spelt out. 198 typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::NamedAlias, 199 llvm::GlobalAlias, 200 &llvm::Module::getNamedAlias> 201 ExplicitRewriteNamedAliasDescriptor; 202 203 /// Represents a rewrite for a regular expression based pattern for functions. 204 /// A pattern for the function name is provided and a transformation for that 205 /// pattern to determine the target function name create the rewrite rule. 206 typedef PatternRewriteDescriptor<RewriteDescriptor::Type::Function, 207 llvm::Function, &llvm::Module::getFunction, 208 &llvm::Module::functions> 209 PatternRewriteFunctionDescriptor; 210 211 /// Represents a rewrite for a global variable based upon a matching pattern. 212 /// Each global variable matching the provided pattern will be transformed as 213 /// described in the transformation pattern for the target. Applies only to 214 /// module level variables. 215 typedef PatternRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable, 216 llvm::GlobalVariable, 217 &llvm::Module::getGlobalVariable, 218 &llvm::Module::globals> 219 PatternRewriteGlobalVariableDescriptor; 220 221 /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global 222 /// aliases which match a given pattern. The provided transformation will be 223 /// applied to each of the matching names. 224 typedef PatternRewriteDescriptor<RewriteDescriptor::Type::NamedAlias, 225 llvm::GlobalAlias, 226 &llvm::Module::getNamedAlias, 227 &llvm::Module::aliases> 228 PatternRewriteNamedAliasDescriptor; 229 230 bool RewriteMapParser::parse(const std::string &MapFile, 231 RewriteDescriptorList *DL) { 232 ErrorOr<std::unique_ptr<MemoryBuffer>> Mapping = 233 MemoryBuffer::getFile(MapFile); 234 235 if (!Mapping) 236 report_fatal_error("unable to read rewrite map '" + MapFile + "': " + 237 Mapping.getError().message()); 238 239 if (!parse(*Mapping, DL)) 240 report_fatal_error("unable to parse rewrite map '" + MapFile + "'"); 241 242 return true; 243 } 244 245 bool RewriteMapParser::parse(std::unique_ptr<MemoryBuffer> &MapFile, 246 RewriteDescriptorList *DL) { 247 SourceMgr SM; 248 yaml::Stream YS(MapFile->getBuffer(), SM); 249 250 for (auto &Document : YS) { 251 yaml::MappingNode *DescriptorList; 252 253 // ignore empty documents 254 if (isa<yaml::NullNode>(Document.getRoot())) 255 continue; 256 257 DescriptorList = dyn_cast<yaml::MappingNode>(Document.getRoot()); 258 if (!DescriptorList) { 259 YS.printError(Document.getRoot(), "DescriptorList node must be a map"); 260 return false; 261 } 262 263 for (auto &Descriptor : *DescriptorList) 264 if (!parseEntry(YS, Descriptor, DL)) 265 return false; 266 } 267 268 return true; 269 } 270 271 bool RewriteMapParser::parseEntry(yaml::Stream &YS, yaml::KeyValueNode &Entry, 272 RewriteDescriptorList *DL) { 273 yaml::ScalarNode *Key; 274 yaml::MappingNode *Value; 275 SmallString<32> KeyStorage; 276 StringRef RewriteType; 277 278 Key = dyn_cast<yaml::ScalarNode>(Entry.getKey()); 279 if (!Key) { 280 YS.printError(Entry.getKey(), "rewrite type must be a scalar"); 281 return false; 282 } 283 284 Value = dyn_cast<yaml::MappingNode>(Entry.getValue()); 285 if (!Value) { 286 YS.printError(Entry.getValue(), "rewrite descriptor must be a map"); 287 return false; 288 } 289 290 RewriteType = Key->getValue(KeyStorage); 291 if (RewriteType.equals("function")) 292 return parseRewriteFunctionDescriptor(YS, Key, Value, DL); 293 else if (RewriteType.equals("global variable")) 294 return parseRewriteGlobalVariableDescriptor(YS, Key, Value, DL); 295 else if (RewriteType.equals("global alias")) 296 return parseRewriteGlobalAliasDescriptor(YS, Key, Value, DL); 297 298 YS.printError(Entry.getKey(), "unknown rewrite type"); 299 return false; 300 } 301 302 bool RewriteMapParser:: 303 parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, 304 yaml::MappingNode *Descriptor, 305 RewriteDescriptorList *DL) { 306 bool Naked = false; 307 std::string Source; 308 std::string Target; 309 std::string Transform; 310 311 for (auto &Field : *Descriptor) { 312 yaml::ScalarNode *Key; 313 yaml::ScalarNode *Value; 314 SmallString<32> KeyStorage; 315 SmallString<32> ValueStorage; 316 StringRef KeyValue; 317 318 Key = dyn_cast<yaml::ScalarNode>(Field.getKey()); 319 if (!Key) { 320 YS.printError(Field.getKey(), "descriptor key must be a scalar"); 321 return false; 322 } 323 324 Value = dyn_cast<yaml::ScalarNode>(Field.getValue()); 325 if (!Value) { 326 YS.printError(Field.getValue(), "descriptor value must be a scalar"); 327 return false; 328 } 329 330 KeyValue = Key->getValue(KeyStorage); 331 if (KeyValue.equals("source")) { 332 std::string Error; 333 334 Source = Value->getValue(ValueStorage); 335 if (!Regex(Source).isValid(Error)) { 336 YS.printError(Field.getKey(), "invalid regex: " + Error); 337 return false; 338 } 339 } else if (KeyValue.equals("target")) { 340 Target = Value->getValue(ValueStorage); 341 } else if (KeyValue.equals("transform")) { 342 Transform = Value->getValue(ValueStorage); 343 } else if (KeyValue.equals("naked")) { 344 std::string Undecorated; 345 346 Undecorated = Value->getValue(ValueStorage); 347 Naked = StringRef(Undecorated).lower() == "true" || Undecorated == "1"; 348 } else { 349 YS.printError(Field.getKey(), "unknown key for function"); 350 return false; 351 } 352 } 353 354 if (Transform.empty() == Target.empty()) { 355 YS.printError(Descriptor, 356 "exactly one of transform or target must be specified"); 357 return false; 358 } 359 360 // TODO see if there is a more elegant solution to selecting the rewrite 361 // descriptor type 362 if (!Target.empty()) 363 DL->push_back(new ExplicitRewriteFunctionDescriptor(Source, Target, Naked)); 364 else 365 DL->push_back(new PatternRewriteFunctionDescriptor(Source, Transform)); 366 367 return true; 368 } 369 370 bool RewriteMapParser:: 371 parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, 372 yaml::MappingNode *Descriptor, 373 RewriteDescriptorList *DL) { 374 std::string Source; 375 std::string Target; 376 std::string Transform; 377 378 for (auto &Field : *Descriptor) { 379 yaml::ScalarNode *Key; 380 yaml::ScalarNode *Value; 381 SmallString<32> KeyStorage; 382 SmallString<32> ValueStorage; 383 StringRef KeyValue; 384 385 Key = dyn_cast<yaml::ScalarNode>(Field.getKey()); 386 if (!Key) { 387 YS.printError(Field.getKey(), "descriptor Key must be a scalar"); 388 return false; 389 } 390 391 Value = dyn_cast<yaml::ScalarNode>(Field.getValue()); 392 if (!Value) { 393 YS.printError(Field.getValue(), "descriptor value must be a scalar"); 394 return false; 395 } 396 397 KeyValue = Key->getValue(KeyStorage); 398 if (KeyValue.equals("source")) { 399 std::string Error; 400 401 Source = Value->getValue(ValueStorage); 402 if (!Regex(Source).isValid(Error)) { 403 YS.printError(Field.getKey(), "invalid regex: " + Error); 404 return false; 405 } 406 } else if (KeyValue.equals("target")) { 407 Target = Value->getValue(ValueStorage); 408 } else if (KeyValue.equals("transform")) { 409 Transform = Value->getValue(ValueStorage); 410 } else { 411 YS.printError(Field.getKey(), "unknown Key for Global Variable"); 412 return false; 413 } 414 } 415 416 if (Transform.empty() == Target.empty()) { 417 YS.printError(Descriptor, 418 "exactly one of transform or target must be specified"); 419 return false; 420 } 421 422 if (!Target.empty()) 423 DL->push_back(new ExplicitRewriteGlobalVariableDescriptor(Source, Target, 424 /*Naked*/false)); 425 else 426 DL->push_back(new PatternRewriteGlobalVariableDescriptor(Source, 427 Transform)); 428 429 return true; 430 } 431 432 bool RewriteMapParser:: 433 parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, 434 yaml::MappingNode *Descriptor, 435 RewriteDescriptorList *DL) { 436 std::string Source; 437 std::string Target; 438 std::string Transform; 439 440 for (auto &Field : *Descriptor) { 441 yaml::ScalarNode *Key; 442 yaml::ScalarNode *Value; 443 SmallString<32> KeyStorage; 444 SmallString<32> ValueStorage; 445 StringRef KeyValue; 446 447 Key = dyn_cast<yaml::ScalarNode>(Field.getKey()); 448 if (!Key) { 449 YS.printError(Field.getKey(), "descriptor key must be a scalar"); 450 return false; 451 } 452 453 Value = dyn_cast<yaml::ScalarNode>(Field.getValue()); 454 if (!Value) { 455 YS.printError(Field.getValue(), "descriptor value must be a scalar"); 456 return false; 457 } 458 459 KeyValue = Key->getValue(KeyStorage); 460 if (KeyValue.equals("source")) { 461 std::string Error; 462 463 Source = Value->getValue(ValueStorage); 464 if (!Regex(Source).isValid(Error)) { 465 YS.printError(Field.getKey(), "invalid regex: " + Error); 466 return false; 467 } 468 } else if (KeyValue.equals("target")) { 469 Target = Value->getValue(ValueStorage); 470 } else if (KeyValue.equals("transform")) { 471 Transform = Value->getValue(ValueStorage); 472 } else { 473 YS.printError(Field.getKey(), "unknown key for Global Alias"); 474 return false; 475 } 476 } 477 478 if (Transform.empty() == Target.empty()) { 479 YS.printError(Descriptor, 480 "exactly one of transform or target must be specified"); 481 return false; 482 } 483 484 if (!Target.empty()) 485 DL->push_back(new ExplicitRewriteNamedAliasDescriptor(Source, Target, 486 /*Naked*/false)); 487 else 488 DL->push_back(new PatternRewriteNamedAliasDescriptor(Source, Transform)); 489 490 return true; 491 } 492 } 493 } 494 495 namespace { 496 class RewriteSymbols : public ModulePass { 497 public: 498 static char ID; // Pass identification, replacement for typeid 499 500 RewriteSymbols(); 501 RewriteSymbols(SymbolRewriter::RewriteDescriptorList &DL); 502 503 bool runOnModule(Module &M) override; 504 505 private: 506 void loadAndParseMapFiles(); 507 508 SymbolRewriter::RewriteDescriptorList Descriptors; 509 }; 510 511 char RewriteSymbols::ID = 0; 512 513 RewriteSymbols::RewriteSymbols() : ModulePass(ID) { 514 initializeRewriteSymbolsPass(*PassRegistry::getPassRegistry()); 515 loadAndParseMapFiles(); 516 } 517 518 RewriteSymbols::RewriteSymbols(SymbolRewriter::RewriteDescriptorList &DL) 519 : ModulePass(ID) { 520 Descriptors.splice(Descriptors.begin(), DL); 521 } 522 523 bool RewriteSymbols::runOnModule(Module &M) { 524 bool Changed; 525 526 Changed = false; 527 for (auto &Descriptor : Descriptors) 528 Changed |= Descriptor.performOnModule(M); 529 530 return Changed; 531 } 532 533 void RewriteSymbols::loadAndParseMapFiles() { 534 const std::vector<std::string> MapFiles(RewriteMapFiles); 535 SymbolRewriter::RewriteMapParser parser; 536 537 for (const auto &MapFile : MapFiles) 538 parser.parse(MapFile, &Descriptors); 539 } 540 } 541 542 INITIALIZE_PASS(RewriteSymbols, "rewrite-symbols", "Rewrite Symbols", false, 543 false) 544 545 ModulePass *llvm::createRewriteSymbolsPass() { return new RewriteSymbols(); } 546 547 ModulePass * 548 llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &DL) { 549 return new RewriteSymbols(DL); 550 } 551