1*333d2b36SAndroid Build Coastguard Worker// Copyright 2023 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker// 15*333d2b36SAndroid Build Coastguard Worker// Note: If you want to know how to use orderfile for your binary or shared 16*333d2b36SAndroid Build Coastguard Worker// library, you can go look at the README in toolchains/pgo-profiles/orderfiles 17*333d2b36SAndroid Build Coastguard Worker 18*333d2b36SAndroid Build Coastguard Workerpackage cc 19*333d2b36SAndroid Build Coastguard Worker 20*333d2b36SAndroid Build Coastguard Workerimport ( 21*333d2b36SAndroid Build Coastguard Worker "fmt" 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 24*333d2b36SAndroid Build Coastguard Worker 25*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 26*333d2b36SAndroid Build Coastguard Worker) 27*333d2b36SAndroid Build Coastguard Worker 28*333d2b36SAndroid Build Coastguard Worker// Order files are text files containing symbols representing functions names. 29*333d2b36SAndroid Build Coastguard Worker// Linkers (lld) uses order files to layout functions in a specific order. 30*333d2b36SAndroid Build Coastguard Worker// These binaries with ordered symbols will reduce page faults and improve a program's launch time 31*333d2b36SAndroid Build Coastguard Worker// due to the efficient loading of symbols during a program’s cold-start. 32*333d2b36SAndroid Build Coastguard Workervar ( 33*333d2b36SAndroid Build Coastguard Worker // Add flags to ignore warnings about symbols not be found 34*333d2b36SAndroid Build Coastguard Worker // or not allowed to be ordered 35*333d2b36SAndroid Build Coastguard Worker orderfileOtherFlags = []string{ 36*333d2b36SAndroid Build Coastguard Worker "-Wl,--no-warn-symbol-ordering", 37*333d2b36SAndroid Build Coastguard Worker } 38*333d2b36SAndroid Build Coastguard Worker 39*333d2b36SAndroid Build Coastguard Worker // Add folder projects for orderfiles 40*333d2b36SAndroid Build Coastguard Worker globalOrderfileProjects = []string{ 41*333d2b36SAndroid Build Coastguard Worker "toolchain/pgo-profiles/orderfiles", 42*333d2b36SAndroid Build Coastguard Worker "vendor/google_data/pgo_profile/orderfiles", 43*333d2b36SAndroid Build Coastguard Worker } 44*333d2b36SAndroid Build Coastguard Worker) 45*333d2b36SAndroid Build Coastguard Worker 46*333d2b36SAndroid Build Coastguard Workervar orderfileProjectsConfigKey = android.NewOnceKey("OrderfileProjects") 47*333d2b36SAndroid Build Coastguard Worker 48*333d2b36SAndroid Build Coastguard Workerconst orderfileProfileFlag = "-forder-file-instrumentation" 49*333d2b36SAndroid Build Coastguard Workerconst orderfileUseFormat = "-Wl,--symbol-ordering-file=%s" 50*333d2b36SAndroid Build Coastguard Worker 51*333d2b36SAndroid Build Coastguard Workerfunc getOrderfileProjects(config android.DeviceConfig) []string { 52*333d2b36SAndroid Build Coastguard Worker return config.OnceStringSlice(orderfileProjectsConfigKey, func() []string { 53*333d2b36SAndroid Build Coastguard Worker return globalOrderfileProjects 54*333d2b36SAndroid Build Coastguard Worker }) 55*333d2b36SAndroid Build Coastguard Worker} 56*333d2b36SAndroid Build Coastguard Worker 57*333d2b36SAndroid Build Coastguard Workertype OrderfileProperties struct { 58*333d2b36SAndroid Build Coastguard Worker Orderfile struct { 59*333d2b36SAndroid Build Coastguard Worker Instrumentation *bool 60*333d2b36SAndroid Build Coastguard Worker Order_file_path *string `android:"arch_variant"` 61*333d2b36SAndroid Build Coastguard Worker Load_order_file *bool `android:"arch_variant"` 62*333d2b36SAndroid Build Coastguard Worker // Additional compiler flags to use when building this module 63*333d2b36SAndroid Build Coastguard Worker // for orderfile profiling. 64*333d2b36SAndroid Build Coastguard Worker Cflags []string `android:"arch_variant"` 65*333d2b36SAndroid Build Coastguard Worker } `android:"arch_variant"` 66*333d2b36SAndroid Build Coastguard Worker 67*333d2b36SAndroid Build Coastguard Worker ShouldProfileModule bool `blueprint:"mutated"` 68*333d2b36SAndroid Build Coastguard Worker OrderfileLoad bool `blueprint:"mutated"` 69*333d2b36SAndroid Build Coastguard Worker OrderfileInstrLink bool `blueprint:"mutated"` 70*333d2b36SAndroid Build Coastguard Worker} 71*333d2b36SAndroid Build Coastguard Worker 72*333d2b36SAndroid Build Coastguard Workertype orderfile struct { 73*333d2b36SAndroid Build Coastguard Worker Properties OrderfileProperties 74*333d2b36SAndroid Build Coastguard Worker} 75*333d2b36SAndroid Build Coastguard Worker 76*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) shouldInstrument() bool { 77*333d2b36SAndroid Build Coastguard Worker return Bool(props.Orderfile.Instrumentation) 78*333d2b36SAndroid Build Coastguard Worker} 79*333d2b36SAndroid Build Coastguard Worker 80*333d2b36SAndroid Build Coastguard Worker// ShouldLoadOrderfile returns true if we need to load the order file rather than 81*333d2b36SAndroid Build Coastguard Worker// profile the binary or shared library 82*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) shouldLoadOrderfile() bool { 83*333d2b36SAndroid Build Coastguard Worker return Bool(props.Orderfile.Load_order_file) && props.Orderfile.Order_file_path != nil 84*333d2b36SAndroid Build Coastguard Worker} 85*333d2b36SAndroid Build Coastguard Worker 86*333d2b36SAndroid Build Coastguard Worker// orderfileEnabled returns true for binaries and shared libraries 87*333d2b36SAndroid Build Coastguard Worker// if instrument flag is set to true 88*333d2b36SAndroid Build Coastguard Workerfunc (orderfile *orderfile) orderfileEnabled() bool { 89*333d2b36SAndroid Build Coastguard Worker return orderfile != nil && orderfile.Properties.shouldInstrument() 90*333d2b36SAndroid Build Coastguard Worker} 91*333d2b36SAndroid Build Coastguard Worker 92*333d2b36SAndroid Build Coastguard Worker// orderfileLinkEnabled returns true for binaries and shared libraries 93*333d2b36SAndroid Build Coastguard Worker// if you should instrument dependencies 94*333d2b36SAndroid Build Coastguard Workerfunc (orderfile *orderfile) orderfileLinkEnabled() bool { 95*333d2b36SAndroid Build Coastguard Worker return orderfile != nil && orderfile.Properties.OrderfileInstrLink 96*333d2b36SAndroid Build Coastguard Worker} 97*333d2b36SAndroid Build Coastguard Worker 98*333d2b36SAndroid Build Coastguard Workerfunc (orderfile *orderfile) props() []interface{} { 99*333d2b36SAndroid Build Coastguard Worker return []interface{}{&orderfile.Properties} 100*333d2b36SAndroid Build Coastguard Worker} 101*333d2b36SAndroid Build Coastguard Worker 102*333d2b36SAndroid Build Coastguard Worker// Get the path to the order file by checking it is valid and not empty 103*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) getOrderfile(ctx BaseModuleContext) android.OptionalPath { 104*333d2b36SAndroid Build Coastguard Worker orderFile := *props.Orderfile.Order_file_path 105*333d2b36SAndroid Build Coastguard Worker 106*333d2b36SAndroid Build Coastguard Worker // Test if the order file is present in any of the Orderfile projects 107*333d2b36SAndroid Build Coastguard Worker for _, profileProject := range getOrderfileProjects(ctx.DeviceConfig()) { 108*333d2b36SAndroid Build Coastguard Worker path := android.ExistentPathForSource(ctx, profileProject, orderFile) 109*333d2b36SAndroid Build Coastguard Worker if path.Valid() { 110*333d2b36SAndroid Build Coastguard Worker return path 111*333d2b36SAndroid Build Coastguard Worker } 112*333d2b36SAndroid Build Coastguard Worker } 113*333d2b36SAndroid Build Coastguard Worker 114*333d2b36SAndroid Build Coastguard Worker // Record that this module's order file is absent 115*333d2b36SAndroid Build Coastguard Worker missing := *props.Orderfile.Order_file_path + ":" + ctx.ModuleDir() + "/Android.bp:" + ctx.ModuleName() 116*333d2b36SAndroid Build Coastguard Worker ctx.getOrCreateMakeVarsInfo().MissingProfile = missing 117*333d2b36SAndroid Build Coastguard Worker 118*333d2b36SAndroid Build Coastguard Worker return android.OptionalPath{} 119*333d2b36SAndroid Build Coastguard Worker} 120*333d2b36SAndroid Build Coastguard Worker 121*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) addInstrumentationProfileGatherFlags(ctx ModuleContext, flags Flags) Flags { 122*333d2b36SAndroid Build Coastguard Worker flags.Local.CFlags = append(flags.Local.CFlags, orderfileProfileFlag) 123*333d2b36SAndroid Build Coastguard Worker flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm -enable-order-file-instrumentation") 124*333d2b36SAndroid Build Coastguard Worker flags.Local.CFlags = append(flags.Local.CFlags, props.Orderfile.Cflags...) 125*333d2b36SAndroid Build Coastguard Worker flags.Local.LdFlags = append(flags.Local.LdFlags, orderfileProfileFlag) 126*333d2b36SAndroid Build Coastguard Worker return flags 127*333d2b36SAndroid Build Coastguard Worker} 128*333d2b36SAndroid Build Coastguard Worker 129*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) loadOrderfileFlags(ctx ModuleContext, file string) []string { 130*333d2b36SAndroid Build Coastguard Worker flags := []string{fmt.Sprintf(orderfileUseFormat, file)} 131*333d2b36SAndroid Build Coastguard Worker flags = append(flags, orderfileOtherFlags...) 132*333d2b36SAndroid Build Coastguard Worker return flags 133*333d2b36SAndroid Build Coastguard Worker} 134*333d2b36SAndroid Build Coastguard Worker 135*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) addLoadFlags(ctx ModuleContext, flags Flags) Flags { 136*333d2b36SAndroid Build Coastguard Worker orderFile := props.getOrderfile(ctx) 137*333d2b36SAndroid Build Coastguard Worker orderFilePath := orderFile.Path() 138*333d2b36SAndroid Build Coastguard Worker loadFlags := props.loadOrderfileFlags(ctx, orderFilePath.String()) 139*333d2b36SAndroid Build Coastguard Worker 140*333d2b36SAndroid Build Coastguard Worker flags.Local.LdFlags = append(flags.Local.LdFlags, loadFlags...) 141*333d2b36SAndroid Build Coastguard Worker 142*333d2b36SAndroid Build Coastguard Worker // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt 143*333d2b36SAndroid Build Coastguard Worker // if orderfile gets updated 144*333d2b36SAndroid Build Coastguard Worker flags.CFlagsDeps = append(flags.CFlagsDeps, orderFilePath) 145*333d2b36SAndroid Build Coastguard Worker flags.LdFlagsDeps = append(flags.LdFlagsDeps, orderFilePath) 146*333d2b36SAndroid Build Coastguard Worker return flags 147*333d2b36SAndroid Build Coastguard Worker} 148*333d2b36SAndroid Build Coastguard Worker 149*333d2b36SAndroid Build Coastguard Workerfunc (orderfile *orderfile) begin(ctx BaseModuleContext) { 150*333d2b36SAndroid Build Coastguard Worker // Currently, we are not enabling orderfiles for host 151*333d2b36SAndroid Build Coastguard Worker if ctx.Host() { 152*333d2b36SAndroid Build Coastguard Worker return 153*333d2b36SAndroid Build Coastguard Worker } 154*333d2b36SAndroid Build Coastguard Worker 155*333d2b36SAndroid Build Coastguard Worker // Currently, we are not enabling orderfiles to begin from static libraries 156*333d2b36SAndroid Build Coastguard Worker if ctx.static() && !ctx.staticBinary() { 157*333d2b36SAndroid Build Coastguard Worker return 158*333d2b36SAndroid Build Coastguard Worker } 159*333d2b36SAndroid Build Coastguard Worker 160*333d2b36SAndroid Build Coastguard Worker if ctx.DeviceConfig().ClangCoverageEnabled() { 161*333d2b36SAndroid Build Coastguard Worker return 162*333d2b36SAndroid Build Coastguard Worker } 163*333d2b36SAndroid Build Coastguard Worker 164*333d2b36SAndroid Build Coastguard Worker // Checking if orderfile is enabled for this module 165*333d2b36SAndroid Build Coastguard Worker if !orderfile.orderfileEnabled() { 166*333d2b36SAndroid Build Coastguard Worker return 167*333d2b36SAndroid Build Coastguard Worker } 168*333d2b36SAndroid Build Coastguard Worker 169*333d2b36SAndroid Build Coastguard Worker orderfile.Properties.OrderfileLoad = orderfile.Properties.shouldLoadOrderfile() 170*333d2b36SAndroid Build Coastguard Worker orderfile.Properties.ShouldProfileModule = !orderfile.Properties.shouldLoadOrderfile() 171*333d2b36SAndroid Build Coastguard Worker orderfile.Properties.OrderfileInstrLink = orderfile.orderfileEnabled() && !orderfile.Properties.shouldLoadOrderfile() 172*333d2b36SAndroid Build Coastguard Worker} 173*333d2b36SAndroid Build Coastguard Worker 174*333d2b36SAndroid Build Coastguard Workerfunc (orderfile *orderfile) flags(ctx ModuleContext, flags Flags) Flags { 175*333d2b36SAndroid Build Coastguard Worker props := orderfile.Properties 176*333d2b36SAndroid Build Coastguard Worker // Add flags to load the orderfile using the path in its Android.bp 177*333d2b36SAndroid Build Coastguard Worker if orderfile.Properties.OrderfileLoad { 178*333d2b36SAndroid Build Coastguard Worker flags = props.addLoadFlags(ctx, flags) 179*333d2b36SAndroid Build Coastguard Worker return flags 180*333d2b36SAndroid Build Coastguard Worker } 181*333d2b36SAndroid Build Coastguard Worker 182*333d2b36SAndroid Build Coastguard Worker // Add flags to profile this module 183*333d2b36SAndroid Build Coastguard Worker if props.ShouldProfileModule { 184*333d2b36SAndroid Build Coastguard Worker flags = props.addInstrumentationProfileGatherFlags(ctx, flags) 185*333d2b36SAndroid Build Coastguard Worker return flags 186*333d2b36SAndroid Build Coastguard Worker } 187*333d2b36SAndroid Build Coastguard Worker 188*333d2b36SAndroid Build Coastguard Worker return flags 189*333d2b36SAndroid Build Coastguard Worker} 190*333d2b36SAndroid Build Coastguard Worker 191*333d2b36SAndroid Build Coastguard Workerfunc orderfilePropagateViaDepTag(tag blueprint.DependencyTag) bool { 192*333d2b36SAndroid Build Coastguard Worker libTag, isLibTag := tag.(libraryDependencyTag) 193*333d2b36SAndroid Build Coastguard Worker // Do not recurse down non-static dependencies 194*333d2b36SAndroid Build Coastguard Worker if isLibTag { 195*333d2b36SAndroid Build Coastguard Worker return libTag.static() 196*333d2b36SAndroid Build Coastguard Worker } else { 197*333d2b36SAndroid Build Coastguard Worker return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag 198*333d2b36SAndroid Build Coastguard Worker } 199*333d2b36SAndroid Build Coastguard Worker} 200*333d2b36SAndroid Build Coastguard Worker 201*333d2b36SAndroid Build Coastguard Worker// orderfileTransitionMutator creates orderfile variants of cc modules. 202*333d2b36SAndroid Build Coastguard Workertype orderfileTransitionMutator struct{} 203*333d2b36SAndroid Build Coastguard Worker 204*333d2b36SAndroid Build Coastguard Workerconst ORDERFILE_VARIATION = "orderfile" 205*333d2b36SAndroid Build Coastguard Worker 206*333d2b36SAndroid Build Coastguard Workerfunc (o *orderfileTransitionMutator) Split(ctx android.BaseModuleContext) []string { 207*333d2b36SAndroid Build Coastguard Worker return []string{""} 208*333d2b36SAndroid Build Coastguard Worker} 209*333d2b36SAndroid Build Coastguard Worker 210*333d2b36SAndroid Build Coastguard Workerfunc (o *orderfileTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { 211*333d2b36SAndroid Build Coastguard Worker if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil { 212*333d2b36SAndroid Build Coastguard Worker if !orderfilePropagateViaDepTag(ctx.DepTag()) { 213*333d2b36SAndroid Build Coastguard Worker return "" 214*333d2b36SAndroid Build Coastguard Worker } 215*333d2b36SAndroid Build Coastguard Worker 216*333d2b36SAndroid Build Coastguard Worker if sourceVariation != "" { 217*333d2b36SAndroid Build Coastguard Worker return sourceVariation 218*333d2b36SAndroid Build Coastguard Worker } 219*333d2b36SAndroid Build Coastguard Worker 220*333d2b36SAndroid Build Coastguard Worker // Propagate profile orderfile flags down from binaries and shared libraries 221*333d2b36SAndroid Build Coastguard Worker if m.orderfile.orderfileLinkEnabled() { 222*333d2b36SAndroid Build Coastguard Worker return ORDERFILE_VARIATION 223*333d2b36SAndroid Build Coastguard Worker } 224*333d2b36SAndroid Build Coastguard Worker } 225*333d2b36SAndroid Build Coastguard Worker return "" 226*333d2b36SAndroid Build Coastguard Worker} 227*333d2b36SAndroid Build Coastguard Worker 228*333d2b36SAndroid Build Coastguard Workerfunc (o *orderfileTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { 229*333d2b36SAndroid Build Coastguard Worker if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil { 230*333d2b36SAndroid Build Coastguard Worker return incomingVariation 231*333d2b36SAndroid Build Coastguard Worker } 232*333d2b36SAndroid Build Coastguard Worker return "" 233*333d2b36SAndroid Build Coastguard Worker} 234*333d2b36SAndroid Build Coastguard Worker 235*333d2b36SAndroid Build Coastguard Workerfunc (o *orderfileTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { 236*333d2b36SAndroid Build Coastguard Worker if variation == "" { 237*333d2b36SAndroid Build Coastguard Worker return 238*333d2b36SAndroid Build Coastguard Worker } 239*333d2b36SAndroid Build Coastguard Worker 240*333d2b36SAndroid Build Coastguard Worker if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil { 241*333d2b36SAndroid Build Coastguard Worker m.Properties.PreventInstall = true 242*333d2b36SAndroid Build Coastguard Worker m.Properties.HideFromMake = true 243*333d2b36SAndroid Build Coastguard Worker m.orderfile.Properties.ShouldProfileModule = true 244*333d2b36SAndroid Build Coastguard Worker // We do not allow propagation for load flags because the orderfile is specific 245*333d2b36SAndroid Build Coastguard Worker // to the module (binary / shared library) 246*333d2b36SAndroid Build Coastguard Worker m.orderfile.Properties.OrderfileLoad = false 247*333d2b36SAndroid Build Coastguard Worker } 248*333d2b36SAndroid Build Coastguard Worker} 249