1/* 2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { ArkStaticInvokeExpr } from '../../core/base/Expr'; 17import { Scene } from '../../Scene'; 18import { Stmt } from '../../core/base/Stmt'; 19import { ArkClass } from '../../core/model/ArkClass'; 20import { NodeID } from '../../core/graph/BaseExplicitGraph'; 21import { CallGraph, CallSite } from '../model/CallGraph'; 22import { AbstractAnalysis } from './AbstractAnalysis'; 23import { CallGraphBuilder } from '../model/builder/CallGraphBuilder'; 24 25export class ClassHierarchyAnalysis extends AbstractAnalysis { 26 constructor(scene: Scene, cg: CallGraph, cb: CallGraphBuilder) { 27 super(scene, cg); 28 this.cgBuilder = cb; 29 } 30 31 public resolveCall(callerMethod: NodeID, invokeStmt: Stmt): CallSite[] { 32 let invokeExpr = invokeStmt.getInvokeExpr(); 33 let resolveResult: CallSite[] = []; 34 35 if (!invokeExpr) { 36 return []; 37 } 38 39 // process anonymous method call 40 this.getParamAnonymousMethod(invokeExpr).forEach(method => { 41 resolveResult.push(new CallSite(invokeStmt, undefined, this.cg.getCallGraphNodeByMethod(method).getID(), callerMethod)); 42 }); 43 44 let calleeMethod = this.resolveInvokeExpr(invokeExpr); 45 if (!calleeMethod) { 46 return resolveResult; 47 } 48 if (invokeExpr instanceof ArkStaticInvokeExpr) { 49 // get specific method 50 resolveResult.push(new CallSite(invokeStmt, undefined, this.cg.getCallGraphNodeByMethod(calleeMethod!.getSignature()).getID(), callerMethod!)); 51 } else { 52 let declareClass = calleeMethod.getDeclaringArkClass(); 53 // TODO: super class method should be placed at the end 54 this.getClassHierarchy(declareClass).forEach((arkClass: ArkClass) => { 55 if (arkClass.isAbstract()) { 56 return; 57 } 58 59 let possibleCalleeMethod = arkClass.getMethodWithName(calleeMethod!.getName()); 60 61 if ( 62 possibleCalleeMethod && 63 possibleCalleeMethod.isGenerated() && 64 arkClass.getSignature().toString() !== declareClass.getSignature().toString() 65 ) { 66 // remove the generated method in extended classes 67 return; 68 } 69 70 if (possibleCalleeMethod && !possibleCalleeMethod.isAbstract()) { 71 resolveResult.push( 72 new CallSite(invokeStmt, undefined, this.cg.getCallGraphNodeByMethod(possibleCalleeMethod.getSignature()).getID(), callerMethod) 73 ); 74 } 75 }); 76 } 77 78 return resolveResult; 79 } 80 81 protected preProcessMethod(): CallSite[] { 82 // do nothing 83 return []; 84 } 85} 86