Add AArch64 device Rust toolchain.

Bug: 141207434
Test: build example rust device module.
Change-Id: I0932a614942bf4a4d4b6c153fcc4fc79c7f202bd
diff --git a/rust/binary.go b/rust/binary.go
index 279c6f5..52f840e 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -71,6 +71,15 @@
 
 func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
 	flags = binary.baseCompiler.compilerFlags(ctx, flags)
+
+	if ctx.toolchain().Bionic() {
+		// no-undefined-version breaks dylib compilation since __rust_*alloc* functions aren't defined, but we can apply this to binaries.
+		flags.LinkFlags = append(flags.LinkFlags,
+			"-Wl,--gc-sections",
+			"-Wl,-z,nocopyreloc",
+			"-Wl,--no-undefined-version")
+	}
+
 	if binary.preferDynamic() {
 		flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic")
 	}
@@ -86,6 +95,12 @@
 		}
 	}
 
+	if ctx.toolchain().Bionic() {
+		deps = binary.baseCompiler.bionicDeps(ctx, deps)
+		deps.CrtBegin = "crtbegin_dynamic"
+		deps.CrtEnd = "crtend_android"
+	}
+
 	return deps
 }
 
diff --git a/rust/builder.go b/rust/builder.go
index ef50701..6611492 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -28,14 +28,14 @@
 		blueprint.RuleParams{
 			Command: "$rustcCmd " +
 				"-C linker=${config.RustLinker} " +
-				"-C link-args=\"${config.RustLinkerArgs} ${linkFlags}\" " +
+				"-C link-args=\"${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}\" " +
 				"-o $out $in ${libFlags} $rustcFlags " +
 				"&& $rustcCmd --emit=dep-info -o $out.d $in ${libFlags} $rustcFlags",
 			CommandDeps: []string{"$rustcCmd"},
 			Depfile:     "$out.d",
 			Deps:        blueprint.DepsGCC, // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
 		},
-		"rustcFlags", "linkFlags", "libFlags")
+		"rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd")
 )
 
 func init() {
@@ -43,19 +43,19 @@
 }
 
 func TransformSrcToBinary(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "bin", includeDirs)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "bin", includeDirs)
 }
 
 func TransformSrctoRlib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "rlib", includeDirs)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "rlib", includeDirs)
 }
 
 func TransformSrctoDylib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "dylib", includeDirs)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "dylib", includeDirs)
 }
 
 func TransformSrctoProcMacro(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "proc-macro", includeDirs)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "proc-macro", includeDirs)
 }
 
 func rustLibsToPaths(libs RustLibraries) android.Paths {
@@ -67,24 +67,28 @@
 }
 
 func transformSrctoCrate(ctx android.ModuleContext, main android.Path,
-	rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string) {
+	rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, crtBegin, crtEnd android.OptionalPath, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string) {
 
 	var inputs android.Paths
 	var deps android.Paths
-	var libFlags, rustcFlags []string
+	var libFlags, rustcFlags, linkFlags []string
 	crate_name := ctx.(ModuleContext).CrateName()
 	targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
 
 	inputs = append(inputs, main)
 
 	// Collect rustc flags
-	rustcFlags = append(rustcFlags, flags.GlobalFlags...)
+	rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
 	rustcFlags = append(rustcFlags, flags.RustFlags...)
 	rustcFlags = append(rustcFlags, "--crate-type="+crate_type)
 	rustcFlags = append(rustcFlags, "--crate-name="+crate_name)
 	if targetTriple != "" {
 		rustcFlags = append(rustcFlags, "--target="+targetTriple)
+		linkFlags = append(linkFlags, "-target "+targetTriple)
 	}
+	// Collect linker flags
+	linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
+	linkFlags = append(linkFlags, flags.LinkFlags...)
 
 	// Collect library/crate flags
 	for _, lib := range rlibs {
@@ -107,6 +111,9 @@
 	deps = append(deps, rustLibsToPaths(proc_macros)...)
 	deps = append(deps, static_libs...)
 	deps = append(deps, shared_libs...)
+	if crtBegin.Valid() {
+		deps = append(deps, crtBegin.Path(), crtEnd.Path())
+	}
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        rustc,
@@ -116,8 +123,10 @@
 		Implicits:   deps,
 		Args: map[string]string{
 			"rustcFlags": strings.Join(rustcFlags, " "),
-			"linkFlags":  strings.Join(flags.LinkFlags, " "),
+			"linkFlags":  strings.Join(linkFlags, " "),
 			"libFlags":   strings.Join(libFlags, " "),
+			"crtBegin":   crtBegin.String(),
+			"crtEnd":     crtEnd.String(),
 		},
 	})
 
diff --git a/rust/compiler.go b/rust/compiler.go
index 87cf08b..f45744b 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -113,7 +113,8 @@
 	flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...)
 	flags.RustFlags = append(flags.RustFlags, "--edition="+*compiler.Properties.Edition)
 	flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
-	flags.GlobalFlags = append(flags.GlobalFlags, ctx.toolchain().ToolchainRustFlags())
+	flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
+	flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags())
 
 	if ctx.Host() && !ctx.Windows() {
 		rpath_prefix := `\$$ORIGIN/`
@@ -148,6 +149,18 @@
 	return deps
 }
 
+func (compiler *baseCompiler) bionicDeps(ctx DepsContext, deps Deps) Deps {
+	deps.SharedLibs = append(deps.SharedLibs, "liblog")
+	deps.SharedLibs = append(deps.SharedLibs, "libc")
+	deps.SharedLibs = append(deps.SharedLibs, "libm")
+	deps.SharedLibs = append(deps.SharedLibs, "libdl")
+
+	//TODO(b/141331117) libstd requires libgcc on Android
+	deps.StaticLibs = append(deps.StaticLibs, "libgcc")
+
+	return deps
+}
+
 func (compiler *baseCompiler) crateName() string {
 	return compiler.Properties.Crate_name
 }
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
new file mode 100644
index 0000000..0264052
--- /dev/null
+++ b/rust/config/arm64_device.go
@@ -0,0 +1,92 @@
+// Copyright 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	Arm64RustFlags            = []string{}
+	Arm64ArchFeatureRustFlags = map[string][]string{}
+	Arm64LinkFlags            = []string{
+		"-Wl,--icf=safe",
+		"-Wl,-z,max-page-size=4096",
+
+		"-Wl,-execute-only",
+	}
+
+	Arm64ArchVariantRustFlags = map[string][]string{
+		"armv8-a":  []string{},
+		"armv8-2a": []string{},
+	}
+)
+
+func init() {
+	registerToolchainFactory(android.Android, android.Arm64, Arm64ToolchainFactory)
+
+	pctx.StaticVariable("Arm64ToolchainRustFlags", strings.Join(Arm64RustFlags, " "))
+	pctx.StaticVariable("Arm64ToolchainLinkFlags", strings.Join(Arm64LinkFlags, " "))
+
+	for variant, rustFlags := range Arm64ArchVariantRustFlags {
+		pctx.StaticVariable("Arm64"+variant+"VariantRustFlags",
+			strings.Join(rustFlags, " "))
+	}
+
+}
+
+type toolchainArm64 struct {
+	toolchain64Bit
+	toolchainRustFlags string
+}
+
+func (t *toolchainArm64) RustTriple() string {
+	return "aarch64-linux-android"
+}
+
+func (t *toolchainArm64) ToolchainLinkFlags() string {
+	return "${config.DeviceGlobalLinkFlags} ${config.Arm64ToolchainLinkFlags}"
+}
+
+func (t *toolchainArm64) ToolchainRustFlags() string {
+	return t.toolchainRustFlags
+}
+
+func (t *toolchainArm64) RustFlags() string {
+	return "${config.Arm64ToolchainRustFlags}"
+}
+
+func (t *toolchainArm64) Supported() bool {
+	return true
+}
+
+func Arm64ToolchainFactory(arch android.Arch) Toolchain {
+	toolchainRustFlags := []string{
+		"${config.Arm64ToolchainRustFlags}",
+		"${config.Arm64" + arch.ArchVariant + "VariantRustFlags}",
+	}
+
+	toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
+	for _, feature := range arch.ArchFeatures {
+		toolchainRustFlags = append(toolchainRustFlags, Arm64ArchFeatureRustFlags[feature]...)
+	}
+
+	return &toolchainArm64{
+		toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
+	}
+}
diff --git a/rust/config/global.go b/rust/config/global.go
index 903a424..cec5a74 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -15,6 +15,8 @@
 package config
 
 import (
+	"strings"
+
 	"android/soong/android"
 	_ "android/soong/cc/config"
 )
@@ -30,6 +32,24 @@
 		"libterm",
 		"libtest",
 	}
+
+	deviceGlobalRustFlags = []string{}
+
+	deviceGlobalLinkFlags = []string{
+		"-Bdynamic",
+		"-nostdlib",
+		"-Wl,-z,noexecstack",
+		"-Wl,-z,relro",
+		"-Wl,-z,now",
+		"-Wl,--build-id=md5",
+		"-Wl,--warn-shared-textrel",
+		"-Wl,--fatal-warnings",
+
+		"-Wl,--pack-dyn-relocs=android+relr",
+		"-Wl,--use-android-relr-tags",
+		"-Wl,--no-undefined",
+		"-Wl,--hash-style=gnu",
+	}
 )
 
 func init() {
@@ -56,4 +76,7 @@
 	pctx.ImportAs("ccConfig", "android/soong/cc/config")
 	pctx.StaticVariable("RustLinker", "${ccConfig.ClangBin}/clang++")
 	pctx.StaticVariable("RustLinkerArgs", "-B ${ccConfig.ClangBin} -fuse-ld=lld")
+
+	pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
+
 }
diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go
index a36d61b..328bca3 100644
--- a/rust/config/toolchain.go
+++ b/rust/config/toolchain.go
@@ -32,6 +32,8 @@
 
 	Is64Bit() bool
 	Supported() bool
+
+	Bionic() bool
 }
 
 type toolchainBase struct {
@@ -53,6 +55,10 @@
 	panic("toolchainBase cannot determine datapath width.")
 }
 
+func (toolchainBase) Bionic() bool {
+	return true
+}
+
 type toolchain64Bit struct {
 	toolchainBase
 }
diff --git a/rust/config/x86_linux_host.go b/rust/config/x86_linux_host.go
index cb6bf1a..5376e5b 100644
--- a/rust/config/x86_linux_host.go
+++ b/rust/config/x86_linux_host.go
@@ -61,6 +61,10 @@
 	return true
 }
 
+func (toolchainLinuxX8664) Bionic() bool {
+	return false
+}
+
 func (t *toolchainLinuxX8664) Name() string {
 	return "x86_64"
 }
@@ -85,6 +89,10 @@
 	return true
 }
 
+func (toolchainLinuxX86) Bionic() bool {
+	return false
+}
+
 func (t *toolchainLinuxX86) Name() string {
 	return "x86"
 }
diff --git a/rust/library.go b/rust/library.go
index 5cf8ac7..c831727 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -191,6 +191,16 @@
 		&library.MutatedProperties)
 }
 
+func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+	deps = library.baseCompiler.compilerDeps(ctx, deps)
+
+	if ctx.toolchain().Bionic() && library.dylib() {
+		deps = library.baseCompiler.bionicDeps(ctx, deps)
+	}
+
+	return deps
+}
+
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
 	var outputFile android.WritablePath
 
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index d4e631b..fa69fbb 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -63,3 +63,8 @@
 
 	return srcPath
 }
+
+func (prebuilt *prebuiltLibraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+	deps = prebuilt.baseCompiler.compilerDeps(ctx, deps)
+	return deps
+}
diff --git a/rust/rust.go b/rust/rust.go
index 359e126..61b51e5 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -43,11 +43,12 @@
 }
 
 type Flags struct {
-	GlobalFlags   []string      // Flags that apply globally
-	RustFlags     []string      // Flags that apply to rust
-	LinkFlags     []string      // Flags that apply to linker
-	RustFlagsDeps android.Paths // Files depended on by compiler flags
-	Toolchain     config.Toolchain
+	GlobalRustFlags []string      // Flags that apply globally to rust
+	GlobalLinkFlags []string      // Flags that apply globally to linker
+	RustFlags       []string      // Flags that apply to rust
+	LinkFlags       []string      // Flags that apply to linker
+	RustFlagsDeps   android.Paths // Files depended on by compiler flags
+	Toolchain       config.Toolchain
 }
 
 type BaseProperties struct {
@@ -92,6 +93,9 @@
 	linkDirs   []string
 	depFlags   []string
 	//ReexportedDeps android.Paths
+
+	CrtBegin android.OptionalPath
+	CrtEnd   android.OptionalPath
 }
 
 type RustLibraries []RustLibrary
@@ -398,6 +402,10 @@
 				directSharedLibDeps = append(directSharedLibDeps, ccDep)
 				mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName)
 				exportDep = true
+			case cc.CrtBeginDepTag():
+				depPaths.CrtBegin = linkFile
+			case cc.CrtEndDepTag():
+				depPaths.CrtEnd = linkFile
 			}
 
 			// Make sure these dependencies are propagated
@@ -480,6 +488,13 @@
 	actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "shared"}), cc.SharedDepTag(), deps.SharedLibs...)
 	actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "static"}), cc.StaticDepTag(), deps.StaticLibs...)
 
+	if deps.CrtBegin != "" {
+		actx.AddVariationDependencies(ccDepVariations, cc.CrtBeginDepTag(), deps.CrtBegin)
+	}
+	if deps.CrtEnd != "" {
+		actx.AddVariationDependencies(ccDepVariations, cc.CrtEndDepTag(), deps.CrtEnd)
+	}
+
 	// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
 	actx.AddFarVariationDependencies([]blueprint.Variation{{Mutator: "arch", Variation: ctx.Config().BuildOsVariant}}, procMacroDepTag, deps.ProcMacros...)
 }