vmbase: Support LLVM and Bionic stack guard

C code compiled with the Android toolchain has stack guard checks
enabled. So as to avoid having to recompile every target with
-fno-stack-guard, instead add the expected symbols to vmbase.

This means we need __stack_chk_guard variable containing the canary
(used by all libc implementations [1]) and a thread-local storage containing
another copy of the canary at offset 40 (Bionic only [2]).

If the instrumentation detects an error, it calls __stack_chk_fail.
Provide an implementation that simply panics.

[1] bionic/tests/stack_protector_test.cpp
[2] https://reviews.llvm.org/D18632

Bug: 237372981
Test: atest vmbase_example.integration_test
Change-Id: I00de7c75aef6a57a73667df6983a12b01fbe9e51
diff --git a/vmbase/example/src/main.rs b/vmbase/example/src/main.rs
index 3c91f97..9b362b2 100644
--- a/vmbase/example/src/main.rs
+++ b/vmbase/example/src/main.rs
@@ -24,7 +24,8 @@
 extern crate alloc;
 
 use crate::layout::{
-    dtb_range, print_addresses, rodata_range, text_range, writable_region, DEVICE_REGION,
+    bionic_tls, dtb_range, print_addresses, rodata_range, stack_chk_guard, text_range,
+    writable_region, DEVICE_REGION,
 };
 use aarch64_paging::{idmap::IdMap, paging::Attributes};
 use alloc::{vec, vec::Vec};
@@ -55,6 +56,7 @@
     print_addresses();
     assert_eq!(arg0, dtb_range().start.0 as u64);
     check_data();
+    check_stack_guard();
 
     unsafe {
         HEAP_ALLOCATOR.lock().init(&mut HEAP as *mut u8 as usize, HEAP.len());
@@ -94,6 +96,13 @@
     check_data();
 }
 
+fn check_stack_guard() {
+    const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
+
+    info!("Testing stack guard");
+    assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
+}
+
 fn check_data() {
     info!("INITIALISED_DATA: {:#010x}", &INITIALISED_DATA as *const u32 as usize);
     unsafe {