Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a74c3e0 authored by Tri Vo's avatar Tri Vo
Browse files

rust: Add HWASan build support

HWASan for static Rust executables is not supported yet.

Bug: 180495975
Test: build local test app with HWASan
Change-Id: I46e851c82a16943586ec3a789f09a58651d036e3
parent 6eafc36e
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -70,6 +70,11 @@ func (mod *Module) AndroidMkEntries() []android.AndroidMkEntries {
		// If the compiler is disabled, this is a SourceProvider.
		mod.SubAndroidMk(&ret, mod.sourceProvider)
	}

	if mod.sanitize != nil {
		mod.SubAndroidMk(&ret, mod.sanitize)
	}

	ret.SubName += mod.Properties.SubName

	return []android.AndroidMkEntries{ret}
+69 −7
Original line number Diff line number Diff line
@@ -23,9 +23,10 @@ import (
)

type SanitizeProperties struct {
	// enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
	// enable AddressSanitizer, HWAddressSanitizer, and others.
	Sanitize struct {
		Address   *bool `android:"arch_variant"`
		Hwaddress *bool `android:"arch_variant"`
		Fuzzer    *bool `android:"arch_variant"`
		Never     *bool `android:"arch_variant"`
	}
@@ -57,6 +58,11 @@ var asanFlags = []string{
	"-Z sanitizer=address",
}

var hwasanFlags = []string{
	"-Z sanitizer=hwaddress",
	"-C target-feature=+tagged-globals",
}

func boolPtr(v bool) *bool {
	if v {
		return &v
@@ -83,6 +89,15 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) {
	if ctx.Os() == android.Android && Bool(s.Address) {
		sanitize.Properties.SanitizerEnabled = true
	}

	// HWASan requires AArch64 hardware feature (top-byte-ignore).
	if ctx.Arch().ArchType != android.Arm64 {
		s.Hwaddress = nil
	}

	if ctx.Os() == android.Android && Bool(s.Hwaddress) {
		sanitize.Properties.SanitizerEnabled = true
	}
}

type sanitize struct {
@@ -99,6 +114,9 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags, deps PathDeps) (
	if Bool(sanitize.Properties.Sanitize.Address) {
		flags.RustFlags = append(flags.RustFlags, asanFlags...)
	}
	if Bool(sanitize.Properties.Sanitize.Hwaddress) {
		flags.RustFlags = append(flags.RustFlags, hwasanFlags...)
	}
	return flags, deps
}

@@ -111,11 +129,38 @@ func rustSanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
		if !mod.Enabled() {
			return
		}

		variations := mctx.Target().Variations()
		var depTag blueprint.DependencyTag
		var deps []string

		if Bool(mod.sanitize.Properties.Sanitize.Fuzzer) || Bool(mod.sanitize.Properties.Sanitize.Address) {
			mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{
				{Mutator: "link", Variation: "shared"},
			}...), cc.SharedDepTag(), config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan"))
			variations = append(variations,
				blueprint.Variation{Mutator: "link", Variation: "shared"})
			depTag = cc.SharedDepTag()
			deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")}
		} else if mod.IsSanitizerEnabled(cc.Hwasan) {
			// TODO(b/180495975): HWASan for static Rust binaries isn't supported yet.
			if binary, ok := mod.compiler.(*binaryDecorator); ok {
				if Bool(binary.Properties.Static_executable) {
					mctx.ModuleErrorf("HWASan is not supported for static Rust executables yet.")
				}
			}

			if mod.StaticallyLinked() {
				variations = append(variations,
					blueprint.Variation{Mutator: "link", Variation: "static"})
				depTag = cc.StaticDepTag(false)
				deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan_static")}
			} else {
				variations = append(variations,
					blueprint.Variation{Mutator: "link", Variation: "shared"})
				depTag = cc.SharedDepTag()
				deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan")}
			}
		}

		mctx.AddFarVariationDependencies(variations, depTag, deps...)
	}
}

@@ -128,6 +173,9 @@ func (sanitize *sanitize) SetSanitizer(t cc.SanitizerType, b bool) {
	case cc.Asan:
		sanitize.Properties.Sanitize.Address = boolPtr(b)
		sanitizerSet = true
	case cc.Hwasan:
		sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
		sanitizerSet = true
	default:
		panic(fmt.Errorf("setting unsupported sanitizerType %d", t))
	}
@@ -169,11 +217,23 @@ func (sanitize *sanitize) getSanitizerBoolPtr(t cc.SanitizerType) *bool {
		return sanitize.Properties.Sanitize.Fuzzer
	case cc.Asan:
		return sanitize.Properties.Sanitize.Address
	case cc.Hwasan:
		return sanitize.Properties.Sanitize.Hwaddress
	default:
		return nil
	}
}

func (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
	// Add a suffix for hwasan rlib libraries to allow surfacing both the sanitized and
	// non-sanitized variants to make without a name conflict.
	if entries.Class == "RLIB_LIBRARIES" || entries.Class == "STATIC_LIBRARIES" {
		if sanitize.isSanitizerEnabled(cc.Hwasan) {
			entries.SubName += ".hwasan"
		}
	}
}

func (mod *Module) SanitizerSupported(t cc.SanitizerType) bool {
	if mod.Host() {
		return false
@@ -183,6 +243,8 @@ func (mod *Module) SanitizerSupported(t cc.SanitizerType) bool {
		return true
	case cc.Asan:
		return true
	case cc.Hwasan:
		return true
	default:
		return false
	}