1 // Copyright 2016 Google Inc. All rights reserved. 2 // 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 package cc 16 17 import ( 18 "path/filepath" 19 20 "github.com/google/blueprint" 21 22 "android/soong/android" 23 ) 24 25 type BinaryLinkerProperties struct { 26 // compile executable with -static 27 Static_executable *bool `android:"arch_variant"` 28 29 // set the name of the output 30 Stem *string `android:"arch_variant"` 31 32 // append to the name of the output 33 Suffix *string `android:"arch_variant"` 34 35 // if set, add an extra objcopy --prefix-symbols= step 36 Prefix_symbols *string 37 38 // if set, install a symlink to the preferred architecture 39 Symlink_preferred_arch *bool `android:"arch_variant"` 40 41 // install symlinks to the binary. Symlink names will have the suffix and the binary 42 // extension (if any) appended 43 Symlinks []string `android:"arch_variant"` 44 45 DynamicLinker string `blueprint:"mutated"` 46 47 // Names of modules to be overridden. Listed modules can only be other binaries 48 // (in Make or Soong). 49 // This does not completely prevent installation of the overridden binaries, but if both 50 // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed 51 // from PRODUCT_PACKAGES. 52 Overrides []string 53 } 54 55 func init() { 56 android.RegisterModuleType("cc_binary", BinaryFactory) 57 android.RegisterModuleType("cc_binary_host", binaryHostFactory) 58 } 59 60 // cc_binary produces a binary that is runnable on a device. 61 func BinaryFactory() android.Module { 62 module, _ := NewBinary(android.HostAndDeviceSupported) 63 return module.Init() 64 } 65 66 // cc_binary_host produces a binary that is runnable on a host. 67 func binaryHostFactory() android.Module { 68 module, _ := NewBinary(android.HostSupported) 69 return module.Init() 70 } 71 72 // 73 // Executables 74 // 75 76 type binaryDecorator struct { 77 *baseLinker 78 *baseInstaller 79 stripper 80 81 Properties BinaryLinkerProperties 82 83 toolPath android.OptionalPath 84 85 // Location of the linked, unstripped binary 86 unstrippedOutputFile android.Path 87 88 // Names of symlinks to be installed for use in LOCAL_MODULE_SYMLINKS 89 symlinks []string 90 91 // Output archive of gcno coverage information 92 coverageOutputFile android.OptionalPath 93 94 // Location of the file that should be copied to dist dir when requested 95 distFile android.OptionalPath 96 97 post_install_cmds []string 98 } 99 100 var _ linker = (*binaryDecorator)(nil) 101 102 func (binary *binaryDecorator) linkerProps() []interface{} { 103 return append(binary.baseLinker.linkerProps(), 104 &binary.Properties, 105 &binary.stripper.StripProperties) 106 107 } 108 109 func (binary *binaryDecorator) getStem(ctx BaseModuleContext) string { 110 stem := ctx.baseModuleName() 111 if String(binary.Properties.Stem) != "" { 112 stem = String(binary.Properties.Stem) 113 } 114 115 return stem + String(binary.Properties.Suffix) 116 } 117 118 func (binary *binaryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { 119 deps = binary.baseLinker.linkerDeps(ctx, deps) 120 if ctx.toolchain().Bionic() { 121 if !Bool(binary.baseLinker.Properties.Nocrt) { 122 if !ctx.useSdk() { 123 if binary.static() { 124 deps.CrtBegin = "crtbegin_static" 125 } else { 126 deps.CrtBegin = "crtbegin_dynamic" 127 } 128 deps.CrtEnd = "crtend_android" 129 } else { 130 // TODO(danalbert): Add generation of crt objects. 131 // For `sdk_version: "current"`, we don't actually have a 132 // freshly generated set of CRT objects. Use the last stable 133 // version. 134 version := ctx.sdkVersion() 135 if version == "current" { 136 version = getCurrentNdkPrebuiltVersion(ctx) 137 } 138 139 if binary.static() { 140 deps.CrtBegin = "ndk_crtbegin_static." + version 141 } else { 142 if binary.static() { 143 deps.CrtBegin = "ndk_crtbegin_static." + version 144 } else { 145 deps.CrtBegin = "ndk_crtbegin_dynamic." + version 146 } 147 deps.CrtEnd = "ndk_crtend_android." + version 148 } 149 } 150 } 151 152 if binary.static() { 153 if ctx.selectedStl() == "libc++_static" { 154 deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl") 155 } 156 // static libraries libcompiler_rt, libc and libc_nomalloc need to be linked with 157 // --start-group/--end-group along with libgcc. If they are in deps.StaticLibs, 158 // move them to the beginning of deps.LateStaticLibs 159 var groupLibs []string 160 deps.StaticLibs, groupLibs = filterList(deps.StaticLibs, 161 []string{"libc", "libc_nomalloc", "libcompiler_rt"}) 162 deps.LateStaticLibs = append(groupLibs, deps.LateStaticLibs...) 163 } 164 165 if ctx.Os() == android.LinuxBionic && !binary.static() { 166 deps.DynamicLinker = "linker" 167 deps.LinkerFlagsFile = "host_bionic_linker_flags" 168 } 169 } 170 171 if !binary.static() && inList("libc", deps.StaticLibs) { 172 ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" + 173 "from static libs or set static_executable: true") 174 } 175 176 return deps 177 } 178 179 func (binary *binaryDecorator) isDependencyRoot() bool { 180 return true 181 } 182 183 func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { 184 module := newModule(hod, android.MultilibFirst) 185 binary := &binaryDecorator{ 186 baseLinker: NewBaseLinker(module.sanitize), 187 baseInstaller: NewBaseInstaller("bin", "", InstallInSystem), 188 } 189 module.compiler = NewBaseCompiler() 190 module.linker = binary 191 module.installer = binary 192 return module, binary 193 } 194 195 func (binary *binaryDecorator) linkerInit(ctx BaseModuleContext) { 196 binary.baseLinker.linkerInit(ctx) 197 198 if !ctx.toolchain().Bionic() { 199 if ctx.Os() == android.Linux { 200 if binary.Properties.Static_executable == nil && ctx.Config().HostStaticBinaries() { 201 binary.Properties.Static_executable = BoolPtr(true) 202 } 203 } else if !ctx.Fuchsia() { 204 // Static executables are not supported on Darwin or Windows 205 binary.Properties.Static_executable = nil 206 } 207 } 208 } 209 210 func (binary *binaryDecorator) static() bool { 211 return Bool(binary.Properties.Static_executable) 212 } 213 214 func (binary *binaryDecorator) staticBinary() bool { 215 return binary.static() 216 } 217 218 func (binary *binaryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { 219 flags = binary.baseLinker.linkerFlags(ctx, flags) 220 221 if ctx.Host() && !ctx.Windows() && !binary.static() { 222 if !ctx.Config().IsEnvTrue("DISABLE_HOST_PIE") { 223 flags.LdFlags = append(flags.LdFlags, "-pie") 224 } 225 } 226 227 // MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because 228 // all code is position independent, and then those warnings get promoted to 229 // errors. 230 if !ctx.Windows() { 231 flags.CFlags = append(flags.CFlags, "-fPIE") 232 } 233 234 if ctx.toolchain().Bionic() { 235 if binary.static() { 236 // Clang driver needs -static to create static executable. 237 // However, bionic/linker uses -shared to overwrite. 238 // Linker for x86 targets does not allow coexistance of -static and -shared, 239 // so we add -static only if -shared is not used. 240 if !inList("-shared", flags.LdFlags) { 241 flags.LdFlags = append(flags.LdFlags, "-static") 242 } 243 244 flags.LdFlags = append(flags.LdFlags, 245 "-nostdlib", 246 "-Bstatic", 247 "-Wl,--gc-sections", 248 ) 249 } else { 250 if flags.DynamicLinker == "" { 251 if binary.Properties.DynamicLinker != "" { 252 flags.DynamicLinker = binary.Properties.DynamicLinker 253 } else { 254 switch ctx.Os() { 255 case android.Android: 256 if ctx.bootstrap() && !ctx.inRecovery() { 257 flags.DynamicLinker = "/system/bin/bootstrap/linker" 258 } else { 259 flags.DynamicLinker = "/system/bin/linker" 260 } 261 if flags.Toolchain.Is64Bit() { 262 flags.DynamicLinker += "64" 263 } 264 case android.LinuxBionic: 265 flags.DynamicLinker = "" 266 default: 267 ctx.ModuleErrorf("unknown dynamic linker") 268 } 269 } 270 271 if ctx.Os() == android.LinuxBionic { 272 // Use the dlwrap entry point, but keep _start around so 273 // that it can be used by host_bionic_inject 274 flags.LdFlags = append(flags.LdFlags, 275 "-Wl,--entry=__dlwrap__start", 276 "-Wl,--undefined=_start", 277 ) 278 } 279 } 280 281 flags.LdFlags = append(flags.LdFlags, 282 "-pie", 283 "-nostdlib", 284 "-Bdynamic", 285 "-Wl,--gc-sections", 286 "-Wl,-z,nocopyreloc", 287 ) 288 } 289 } else { 290 if binary.static() { 291 flags.LdFlags = append(flags.LdFlags, "-static") 292 } 293 if ctx.Darwin() { 294 flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names") 295 } 296 } 297 298 return flags 299 } 300 301 func (binary *binaryDecorator) link(ctx ModuleContext, 302 flags Flags, deps PathDeps, objs Objects) android.Path { 303 304 fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix() 305 outputFile := android.PathForModuleOut(ctx, fileName) 306 ret := outputFile 307 308 var linkerDeps android.Paths 309 310 if deps.LinkerFlagsFile.Valid() { 311 flags.LdFlags = append(flags.LdFlags, "$$(cat "+deps.LinkerFlagsFile.String()+")") 312 linkerDeps = append(linkerDeps, deps.LinkerFlagsFile.Path()) 313 } 314 315 if flags.DynamicLinker != "" { 316 flags.LdFlags = append(flags.LdFlags, "-Wl,-dynamic-linker,"+flags.DynamicLinker) 317 } else if ctx.toolchain().Bionic() && !binary.static() { 318 flags.LdFlags = append(flags.LdFlags, "-Wl,--no-dynamic-linker") 319 } 320 321 builderFlags := flagsToBuilderFlags(flags) 322 323 if binary.stripper.needsStrip(ctx) { 324 if ctx.Darwin() { 325 builderFlags.stripUseGnuStrip = true 326 } 327 strippedOutputFile := outputFile 328 outputFile = android.PathForModuleOut(ctx, "unstripped", fileName) 329 binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags) 330 } 331 332 binary.unstrippedOutputFile = outputFile 333 334 if String(binary.Properties.Prefix_symbols) != "" { 335 afterPrefixSymbols := outputFile 336 outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName) 337 TransformBinaryPrefixSymbols(ctx, String(binary.Properties.Prefix_symbols), outputFile, 338 flagsToBuilderFlags(flags), afterPrefixSymbols) 339 } 340 341 if Bool(binary.baseLinker.Properties.Use_version_lib) { 342 if ctx.Host() { 343 versionedOutputFile := outputFile 344 outputFile = android.PathForModuleOut(ctx, "unversioned", fileName) 345 binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile) 346 } else { 347 versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName) 348 binary.distFile = android.OptionalPathForPath(versionedOutputFile) 349 350 if binary.stripper.needsStrip(ctx) { 351 out := android.PathForModuleOut(ctx, "versioned-stripped", fileName) 352 binary.distFile = android.OptionalPathForPath(out) 353 binary.stripper.strip(ctx, versionedOutputFile, out, builderFlags) 354 } 355 356 binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile) 357 } 358 } 359 360 if ctx.Os() == android.LinuxBionic && !binary.static() { 361 injectedOutputFile := outputFile 362 outputFile = android.PathForModuleOut(ctx, "prelinker", fileName) 363 364 if !deps.DynamicLinker.Valid() { 365 panic("Non-static host bionic modules must have a dynamic linker") 366 } 367 368 binary.injectHostBionicLinkerSymbols(ctx, outputFile, deps.DynamicLinker.Path(), injectedOutputFile) 369 } 370 371 var sharedLibs android.Paths 372 // Ignore shared libs for static executables. 373 if !binary.static() { 374 sharedLibs = deps.EarlySharedLibs 375 sharedLibs = append(sharedLibs, deps.SharedLibs...) 376 sharedLibs = append(sharedLibs, deps.LateSharedLibs...) 377 linkerDeps = append(linkerDeps, deps.EarlySharedLibsDeps...) 378 linkerDeps = append(linkerDeps, deps.SharedLibsDeps...) 379 linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...) 380 } 381 382 linkerDeps = append(linkerDeps, objs.tidyFiles...) 383 linkerDeps = append(linkerDeps, flags.LdFlagsDeps...) 384 385 TransformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, deps.StaticLibs, 386 deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true, 387 builderFlags, outputFile) 388 389 objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...) 390 objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...) 391 binary.coverageOutputFile = TransformCoverageFilesToLib(ctx, objs, builderFlags, binary.getStem(ctx)) 392 393 // Need to determine symlinks early since some targets (ie APEX) need this 394 // information but will not call 'install' 395 for _, symlink := range binary.Properties.Symlinks { 396 binary.symlinks = append(binary.symlinks, 397 symlink+String(binary.Properties.Suffix)+ctx.toolchain().ExecutableSuffix()) 398 } 399 400 if Bool(binary.Properties.Symlink_preferred_arch) { 401 if String(binary.Properties.Stem) == "" && String(binary.Properties.Suffix) == "" { 402 ctx.PropertyErrorf("symlink_preferred_arch", "must also specify stem or suffix") 403 } 404 if ctx.TargetPrimary() { 405 binary.symlinks = append(binary.symlinks, ctx.baseModuleName()) 406 } 407 } 408 409 return ret 410 } 411 412 func (binary *binaryDecorator) unstrippedOutputFilePath() android.Path { 413 return binary.unstrippedOutputFile 414 } 415 416 func (binary *binaryDecorator) symlinkList() []string { 417 return binary.symlinks 418 } 419 420 func (binary *binaryDecorator) nativeCoverage() bool { 421 return true 422 } 423 424 // /system/bin/linker -> /apex/com.android.runtime/bin/linker 425 func (binary *binaryDecorator) installSymlinkToRuntimeApex(ctx ModuleContext, file android.Path) { 426 dir := binary.baseInstaller.installDir(ctx) 427 dirOnDevice := android.InstallPathToOnDevicePath(ctx, dir) 428 target := "/" + filepath.Join("apex", "com.android.runtime", dir.Base(), file.Base()) 429 430 ctx.InstallAbsoluteSymlink(dir, file.Base(), target) 431 binary.post_install_cmds = append(binary.post_install_cmds, makeSymlinkCmd(dirOnDevice, file.Base(), target)) 432 433 for _, symlink := range binary.symlinks { 434 ctx.InstallAbsoluteSymlink(dir, symlink, target) 435 binary.post_install_cmds = append(binary.post_install_cmds, makeSymlinkCmd(dirOnDevice, symlink, target)) 436 } 437 } 438 439 func (binary *binaryDecorator) install(ctx ModuleContext, file android.Path) { 440 // Bionic binaries (e.g. linker) is installed to the bootstrap subdirectory. 441 // The original path becomes a symlink to the corresponding file in the 442 // runtime APEX. 443 if isBionic(ctx.baseModuleName()) && ctx.Arch().Native && ctx.apexName() == "" && !ctx.inRecovery() { 444 if ctx.Device() { 445 binary.installSymlinkToRuntimeApex(ctx, file) 446 } 447 binary.baseInstaller.subDir = "bootstrap" 448 } 449 binary.baseInstaller.install(ctx, file) 450 for _, symlink := range binary.symlinks { 451 ctx.InstallSymlink(binary.baseInstaller.installDir(ctx), symlink, binary.baseInstaller.path) 452 } 453 454 if ctx.Os().Class == android.Host { 455 binary.toolPath = android.OptionalPathForPath(binary.baseInstaller.path) 456 } 457 } 458 459 func (binary *binaryDecorator) hostToolPath() android.OptionalPath { 460 return binary.toolPath 461 } 462 463 func init() { 464 pctx.HostBinToolVariable("hostBionicSymbolsInjectCmd", "host_bionic_inject") 465 } 466 467 var injectHostBionicSymbols = pctx.AndroidStaticRule("injectHostBionicSymbols", 468 blueprint.RuleParams{ 469 Command: "$hostBionicSymbolsInjectCmd -i $in -l $linker -o $out", 470 CommandDeps: []string{"$hostBionicSymbolsInjectCmd"}, 471 }, "linker") 472 473 func (binary *binaryDecorator) injectHostBionicLinkerSymbols(ctx ModuleContext, in, linker android.Path, out android.WritablePath) { 474 ctx.Build(pctx, android.BuildParams{ 475 Rule: injectHostBionicSymbols, 476 Description: "inject host bionic symbols", 477 Input: in, 478 Implicit: linker, 479 Output: out, 480 Args: map[string]string{ 481 "linker": linker.String(), 482 }, 483 }) 484 } 485