Add support for AArch64 XOM binaries.

Adds build system support for generating AArch64 binaries with
execute-only memory layouts via a new xom module property. Also adds
support for an ENABLE_XOM build flag for global builds.

Bug: 77958880
Test: make -j ENABLE_XOM=true
Change-Id: Ia2ea981498dd12941aaf5ca807648ae37527e3ee
diff --git a/cc/cc.go b/cc/cc.go
index 5485ae3..3aaaf39 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -360,6 +360,7 @@
 	vndkdep   *vndkdep
 	lto       *lto
 	pgo       *pgo
+	xom       *xom
 
 	androidMkSharedLibDeps []string
 
@@ -417,6 +418,9 @@
 	if c.pgo != nil {
 		c.AddProperties(c.pgo.props()...)
 	}
+	if c.xom != nil {
+		c.AddProperties(c.xom.props()...)
+	}
 	for _, feature := range c.features {
 		c.AddProperties(feature.props()...)
 	}
@@ -658,6 +662,7 @@
 	module.vndkdep = &vndkdep{}
 	module.lto = &lto{}
 	module.pgo = &pgo{}
+	module.xom = &xom{}
 	return module
 }
 
@@ -774,6 +779,9 @@
 	if c.pgo != nil {
 		flags = c.pgo.flags(ctx, flags)
 	}
+	if c.xom != nil {
+		flags = c.xom.flags(ctx, flags)
+	}
 	for _, feature := range c.features {
 		flags = feature.flags(ctx, flags)
 	}
@@ -1641,6 +1649,7 @@
 		&VndkProperties{},
 		&LTOProperties{},
 		&PgoProperties{},
+		&XomProperties{},
 		&android.ProtoProperties{},
 	)
 
diff --git a/cc/xom.go b/cc/xom.go
new file mode 100644
index 0000000..f65fc24
--- /dev/null
+++ b/cc/xom.go
@@ -0,0 +1,75 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import (
+	"android/soong/android"
+)
+
+type XomProperties struct {
+	Xom *bool
+}
+
+type xom struct {
+	Properties XomProperties
+}
+
+func (xom *xom) props() []interface{} {
+	return []interface{}{&xom.Properties}
+}
+
+func (xom *xom) begin(ctx BaseModuleContext) {}
+
+func (xom *xom) deps(ctx BaseModuleContext, deps Deps) Deps {
+	return deps
+}
+
+func (xom *xom) flags(ctx ModuleContext, flags Flags) Flags {
+	disableXom := false
+
+	if !ctx.Config().EnableXOM() || ctx.Config().XOMDisabledForPath(ctx.ModuleDir()) {
+		disableXom = true
+	}
+
+	if xom.Properties.Xom != nil && !*xom.Properties.Xom {
+		return flags
+	}
+
+	// If any static dependencies have XOM disabled, we should disable XOM in this module,
+	// the assumption being if it's been explicitly disabled then there's probably incompatible
+	// code in the library which may get pulled in.
+	if !ctx.static() && !disableXom {
+		ctx.VisitDirectDeps(func(m android.Module) {
+			cc, ok := m.(*Module)
+			if !ok || cc.xom == nil || !cc.static() {
+				return
+			}
+			if cc.xom.Properties.Xom != nil && !*cc.xom.Properties.Xom {
+				disableXom = true
+				return
+			}
+		})
+	}
+
+	// Enable execute-only if none of the dependencies disable it,
+	// also if it's explicitly set true (allows overriding dependencies disabling it).
+	if !disableXom || (xom.Properties.Xom != nil && *xom.Properties.Xom) {
+		if ctx.Arch().ArchType == android.Arm64 {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-execute-only")
+		}
+	}
+
+	return flags
+}