11e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar/* 21e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * Copyright 2014, The Android Open Source Project 31e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * 41e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * Licensed under the Apache License, Version 2.0 (the "License"); 51e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * you may not use this file except in compliance with the License. 61e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * You may obtain a copy of the License at 71e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * 81e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * http://www.apache.org/licenses/LICENSE-2.0 91e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * 101e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * Unless required by applicable law or agreed to in writing, software 111e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * distributed under the License is distributed on an "AS IS" BASIS, 121e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * See the License for the specific language governing permissions and 141e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar * limitations under the License. 151e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar */ 161e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 17a2dd52f0710c214e00c1a13e25116e1af5eec77aJean-Luc Brouillet#include "Log.h" 18a2dd52f0710c214e00c1a13e25116e1af5eec77aJean-Luc Brouillet#include "RSTransforms.h" 191e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar#include "RSStubsWhiteList.h" 201e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 211e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar#include <cstdlib> 221e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 231e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar#include <llvm/IR/Instructions.h> 241e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar#include <llvm/IR/Module.h> 251e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar#include <llvm/IR/Function.h> 261e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar#include <llvm/Pass.h> 271e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 281e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainarnamespace { // anonymous namespace 291e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 301e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar// Create a Module pass that screens all the global functions in the 311e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar// module and check if any disallowed external function is accessible 321e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar// and potentially callable. 331e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainarclass RSScreenFunctionsPass : public llvm::ModulePass { 341e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainarprivate: 351e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar static char ID; 361e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 371e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar std::vector<std::string> &whiteList = stubList; 381e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 398a019dd0040bedf5078e4d18e06a244a675b80e8Chih-Hung Hsieh bool isPresent(std::vector<std::string> &list, const std::string &name) { 401e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar auto lower = std::lower_bound(list.begin(), 411e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar list.end(), 421e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar name); 431e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 441e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar if (lower != list.end() && name.compare(*lower) == 0) 451e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar return true; 461e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar return false; 471e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar } 481e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 491e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar bool isLegal(llvm::Function &F) { 501e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar // A global function symbol is legal if 511e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar // a. it has a body, i.e. is not empty or 521e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar // b. its name starts with "llvm." or 531e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar // c. it is present in the whitelist 541e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 551e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar if (!F.empty()) 561e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar return true; 571e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 581e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar llvm::StringRef FName = F.getName(); 591e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar if (FName.startswith("llvm.")) 601e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar return true; 611e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 621e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar if (isPresent(whiteList, FName.str())) 631e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar return true; 641e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 651e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar return false; 661e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar } 671e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 681e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainarpublic: 695db508c73e6177eb306bac4725616b7c001587c4Stephen Hines RSScreenFunctionsPass() 705db508c73e6177eb306bac4725616b7c001587c4Stephen Hines : ModulePass (ID) { 711e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar std::sort(whiteList.begin(), whiteList.end()); 721e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar } 731e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 74c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { 75c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines AU.setPreservesAll(); 76c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines } 77c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines 781e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar bool runOnModule(llvm::Module &M) override { 795db508c73e6177eb306bac4725616b7c001587c4Stephen Hines bool failed = false; 801e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 811e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar auto &FunctionList(M.getFunctionList()); 821e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar for(auto &F: FunctionList) { 831e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar if (!isLegal(F)) { 841e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar ALOGE("Call to function %s from RenderScript is disallowed\n", 851e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar F.getName().str().c_str()); 865db508c73e6177eb306bac4725616b7c001587c4Stephen Hines failed = true; 871e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar } 881e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar } 891e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 905db508c73e6177eb306bac4725616b7c001587c4Stephen Hines if (failed) { 915db508c73e6177eb306bac4725616b7c001587c4Stephen Hines llvm::report_fatal_error("Use of undefined external function"); 925db508c73e6177eb306bac4725616b7c001587c4Stephen Hines } 935db508c73e6177eb306bac4725616b7c001587c4Stephen Hines 941e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar return false; 951e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar } 961e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 971e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar}; 981e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 991e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar} 1001e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 1011e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainarchar RSScreenFunctionsPass::ID = 0; 1021e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 1031e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainarnamespace bcc { 1041e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 1051e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainarllvm::ModulePass * 1065db508c73e6177eb306bac4725616b7c001587c4Stephen HinescreateRSScreenFunctionsPass() { 1075db508c73e6177eb306bac4725616b7c001587c4Stephen Hines return new RSScreenFunctionsPass(); 1081e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar} 1091e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar 1101e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar} 111