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