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 "github.com/google/blueprint/proptools" 22 23 "android/soong/android" 24 ) 25 26 type BinaryLinkerProperties struct { 27 // compile executable with -static 28 Static_executable *bool `android:"arch_variant"` 29 30 // set the name of the output 31 Stem string `android:"arch_variant"` 32 33 // append to the name of the output 34 Suffix string `android:"arch_variant"` 35 36 // if set, add an extra objcopy --prefix-symbols= step 37 Prefix_symbols string 38 39 // if set, install a symlink to the preferred architecture 40 Symlink_preferred_arch bool 41 42 // install symlinks to the binary. Symlink names will have the suffix and the binary 43 // extension (if any) appended 44 Symlinks []string `android:"arch_variant"` 45 46 // do not pass -pie 47 No_pie *bool `android:"arch_variant"` 48 49 DynamicLinker string `blueprint:"mutated"` 50 } 51 52 func init() { 53 android.RegisterModuleType("cc_binary", binaryFactory) 54 android.RegisterModuleType("cc_binary_host", binaryHostFactory) 55 } 56 57 // Module factory for binaries 58 func binaryFactory() (blueprint.Module, []interface{}) { 59 module, _ := NewBinary(android.HostAndDeviceSupported) 60 return module.Init() 61 } 62 63 // Module factory for host binaries 64 func binaryHostFactory() (blueprint.Module, []interface{}) { 65 module, _ := NewBinary(android.HostSupported) 66 return module.Init() 67 } 68 69 // 70 // Executables 71 // 72 73 type binaryDecorator struct { 74 *baseLinker 75 *baseInstaller 76 stripper 77 78 Properties BinaryLinkerProperties 79 80 toolPath android.OptionalPath 81 82 // Names of symlinks to be installed for use in LOCAL_MODULE_SYMLINKS 83 symlinks []string 84 85 // Output archive of gcno coverage information 86 coverageOutputFile android.OptionalPath 87 } 88 89 var _ linker = (*binaryDecorator)(nil) 90 91 func (binary *binaryDecorator) linkerProps() []interface{} { 92 return append(binary.baseLinker.linkerProps(), 93 &binary.Properties, 94 &binary.stripper.StripProperties) 95 96 } 97 98 func (binary *binaryDecorator) getStem(ctx BaseModuleContext) string { 99 stem := ctx.baseModuleName() 100 if binary.Properties.Stem != "" { 101 stem = binary.Properties.Stem 102 } 103 104 return stem + binary.Properties.Suffix 105 } 106 107 func (binary *binaryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { 108 deps = binary.baseLinker.linkerDeps(ctx, deps) 109 if ctx.toolchain().Bionic() { 110 if !Bool(binary.baseLinker.Properties.Nocrt) { 111 if !ctx.sdk() { 112 if binary.static() { 113 deps.CrtBegin = "crtbegin_static" 114 } else { 115 deps.CrtBegin = "crtbegin_dynamic" 116 } 117 deps.CrtEnd = "crtend_android" 118 } else { 119 // TODO(danalbert): Add generation of crt objects. 120 // For `sdk_version: "current"`, we don't actually have a 121 // freshly generated set of CRT objects. Use the last stable 122 // version. 123 version := ctx.sdkVersion() 124 if version == "current" { 125 version = ctx.AConfig().PlatformSdkVersion() 126 } 127 128 if binary.static() { 129 deps.CrtBegin = "ndk_crtbegin_static." + version 130 } else { 131 if binary.static() { 132 deps.CrtBegin = "ndk_crtbegin_static." + version 133 } else { 134 deps.CrtBegin = "ndk_crtbegin_dynamic." + version 135 } 136 deps.CrtEnd = "ndk_crtend_android." + version 137 } 138 } 139 } 140 141 if binary.static() { 142 if ctx.selectedStl() == "libc++_static" { 143 deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl") 144 } 145 // static libraries libcompiler_rt, libc and libc_nomalloc need to be linked with 146 // --start-group/--end-group along with libgcc. If they are in deps.StaticLibs, 147 // move them to the beginning of deps.LateStaticLibs 148 var groupLibs []string 149 deps.StaticLibs, groupLibs = filterList(deps.StaticLibs, 150 []string{"libc", "libc_nomalloc", "libcompiler_rt"}) 151 deps.LateStaticLibs = append(groupLibs, deps.LateStaticLibs...) 152 } 153 } 154 155 if !binary.static() && inList("libc", deps.StaticLibs) { 156 ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" + 157 "from static libs or set static_executable: true") 158 } 159 return deps 160 } 161 162 func (binary *binaryDecorator) isDependencyRoot() bool { 163 return true 164 } 165 166 func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { 167 module := newModule(hod, android.MultilibFirst) 168 binary := &binaryDecorator{ 169 baseLinker: NewBaseLinker(), 170 baseInstaller: NewBaseInstaller("bin", "", InstallInSystem), 171 } 172 module.compiler = NewBaseCompiler() 173 module.linker = binary 174 module.installer = binary 175 return module, binary 176 } 177 178 func (binary *binaryDecorator) linkerInit(ctx BaseModuleContext) { 179 binary.baseLinker.linkerInit(ctx) 180 181 if !ctx.toolchain().Bionic() { 182 if ctx.Os() == android.Linux { 183 if binary.Properties.Static_executable == nil && Bool(ctx.AConfig().ProductVariables.HostStaticBinaries) { 184 binary.Properties.Static_executable = proptools.BoolPtr(true) 185 } 186 } else { 187 // Static executables are not supported on Darwin or Windows 188 binary.Properties.Static_executable = nil 189 } 190 } 191 } 192 193 func (binary *binaryDecorator) static() bool { 194 return Bool(binary.Properties.Static_executable) 195 } 196 197 func (binary *binaryDecorator) staticBinary() bool { 198 return binary.static() 199 } 200 201 func (binary *binaryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { 202 flags = binary.baseLinker.linkerFlags(ctx, flags) 203 204 if ctx.Host() && !binary.static() { 205 if !ctx.AConfig().IsEnvTrue("DISABLE_HOST_PIE") { 206 flags.LdFlags = append(flags.LdFlags, "-pie") 207 if ctx.Os() == android.Windows { 208 flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup") 209 } 210 } 211 } 212 213 // MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because 214 // all code is position independent, and then those warnings get promoted to 215 // errors. 216 if ctx.Os() != android.Windows { 217 flags.CFlags = append(flags.CFlags, "-fpie") 218 } 219 220 if ctx.toolchain().Bionic() { 221 if binary.static() { 222 // Clang driver needs -static to create static executable. 223 // However, bionic/linker uses -shared to overwrite. 224 // Linker for x86 targets does not allow coexistance of -static and -shared, 225 // so we add -static only if -shared is not used. 226 if !inList("-shared", flags.LdFlags) { 227 flags.LdFlags = append(flags.LdFlags, "-static") 228 } 229 230 flags.LdFlags = append(flags.LdFlags, 231 "-nostdlib", 232 "-Bstatic", 233 "-Wl,--gc-sections", 234 ) 235 236 } else { 237 if flags.DynamicLinker == "" { 238 if binary.Properties.DynamicLinker != "" { 239 flags.DynamicLinker = binary.Properties.DynamicLinker 240 } else { 241 switch ctx.Os() { 242 case android.Android: 243 flags.DynamicLinker = "/system/bin/linker" 244 case android.LinuxBionic: 245 // The linux kernel expects the linker to be an 246 // absolute path 247 path := android.PathForOutput(ctx, 248 "host", "linux_bionic-x86", "bin", "linker") 249 if p, err := filepath.Abs(path.String()); err == nil { 250 flags.DynamicLinker = p 251 } else { 252 ctx.ModuleErrorf("can't find path to dynamic linker: %q", err) 253 } 254 default: 255 ctx.ModuleErrorf("unknown dynamic linker") 256 } 257 if flags.Toolchain.Is64Bit() { 258 flags.DynamicLinker += "64" 259 } 260 } 261 } 262 263 flags.LdFlags = append(flags.LdFlags, 264 "-pie", 265 "-nostdlib", 266 "-Bdynamic", 267 "-Wl,--gc-sections", 268 "-Wl,-z,nocopyreloc", 269 ) 270 } 271 } else { 272 if binary.static() { 273 flags.LdFlags = append(flags.LdFlags, "-static") 274 } 275 if ctx.Darwin() { 276 flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names") 277 } 278 } 279 280 return flags 281 } 282 283 func (binary *binaryDecorator) link(ctx ModuleContext, 284 flags Flags, deps PathDeps, objs Objects) android.Path { 285 286 fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix() 287 outputFile := android.PathForModuleOut(ctx, fileName) 288 ret := outputFile 289 290 var linkerDeps android.Paths 291 292 sharedLibs := deps.SharedLibs 293 sharedLibs = append(sharedLibs, deps.LateSharedLibs...) 294 295 if flags.DynamicLinker != "" { 296 flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker) 297 } 298 299 builderFlags := flagsToBuilderFlags(flags) 300 301 if binary.stripper.needsStrip(ctx) { 302 strippedOutputFile := outputFile 303 outputFile = android.PathForModuleOut(ctx, "unstripped", fileName) 304 binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags) 305 } 306 307 if binary.Properties.Prefix_symbols != "" { 308 afterPrefixSymbols := outputFile 309 outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName) 310 TransformBinaryPrefixSymbols(ctx, binary.Properties.Prefix_symbols, outputFile, 311 flagsToBuilderFlags(flags), afterPrefixSymbols) 312 } 313 314 linkerDeps = append(linkerDeps, deps.SharedLibsDeps...) 315 linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...) 316 linkerDeps = append(linkerDeps, objs.tidyFiles...) 317 318 TransformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, deps.StaticLibs, 319 deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true, 320 builderFlags, outputFile) 321 322 objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...) 323 objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...) 324 binary.coverageOutputFile = TransformCoverageFilesToLib(ctx, objs, builderFlags, binary.getStem(ctx)) 325 326 return ret 327 } 328 329 func (binary *binaryDecorator) install(ctx ModuleContext, file android.Path) { 330 binary.baseInstaller.install(ctx, file) 331 for _, symlink := range binary.Properties.Symlinks { 332 binary.symlinks = append(binary.symlinks, 333 symlink+binary.Properties.Suffix+ctx.toolchain().ExecutableSuffix()) 334 } 335 336 if binary.Properties.Symlink_preferred_arch { 337 if binary.Properties.Stem == "" && binary.Properties.Suffix == "" { 338 ctx.PropertyErrorf("symlink_preferred_arch", "must also specify stem or suffix") 339 } 340 if ctx.TargetPrimary() { 341 binary.symlinks = append(binary.symlinks, ctx.baseModuleName()) 342 } 343 } 344 345 for _, symlink := range binary.symlinks { 346 ctx.InstallSymlink(binary.baseInstaller.installDir(ctx), symlink, binary.baseInstaller.path) 347 } 348 349 if ctx.Os().Class == android.Host { 350 binary.toolPath = android.OptionalPathForPath(binary.baseInstaller.path) 351 } 352 } 353 354 func (binary *binaryDecorator) hostToolPath() android.OptionalPath { 355 return binary.toolPath 356 } 357