Merge "Preserve x18 while calling aptX encoder libraries."
diff --git a/common/scoped_scs_exit.h b/common/scoped_scs_exit.h
new file mode 100644
index 0000000..ad4a8d6
--- /dev/null
+++ b/common/scoped_scs_exit.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+// Prevent x18 (shadow call stack address) from being clobbered by functions
+// called by a function that declares a variable of this type by temporarily
+// storing the value on the stack. This is used only when calling out to certain
+// vendor libraries.
+struct ScopedSCSExit {
+#ifdef __aarch64__
+ void* scs;
+
+ __attribute__((always_inline, no_sanitize("shadow-call-stack"))) ScopedSCSExit() {
+ __asm__ __volatile__("str x18, [%0]" ::"r"(&scs));
+ }
+
+ __attribute__((always_inline, no_sanitize("shadow-call-stack"))) ~ScopedSCSExit() {
+ __asm__ __volatile__("ldr x18, [%0]; str xzr, [%0]" ::"r"(&scs));
+ }
+#else
+ // Silence unused variable warnings in non-SCS builds.
+ __attribute__((no_sanitize("shadow-call-stack"))) ScopedSCSExit() {}
+ __attribute__((no_sanitize("shadow-call-stack"))) ~ScopedSCSExit() {}
+#endif
+};
diff --git a/stack/a2dp/a2dp_vendor_aptx_encoder.cc b/stack/a2dp/a2dp_vendor_aptx_encoder.cc
index 0d605c0..e7d0145 100644
--- a/stack/a2dp/a2dp_vendor_aptx_encoder.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_encoder.cc
@@ -26,6 +26,7 @@
#include "a2dp_vendor.h"
#include "a2dp_vendor_aptx.h"
#include "bt_common.h"
+#include "common/scoped_scs_exit.h"
#include "common/time_util.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -54,6 +55,25 @@
static tAPTX_ENCODER_ENCODE_STEREO aptx_encoder_encode_stereo_func;
static tAPTX_ENCODER_SIZEOF_PARAMS aptx_encoder_sizeof_params_func;
+__attribute__((no_sanitize("shadow-call-stack")))
+static int aptx_encoder_init(void* state, short endian) {
+ ScopedSCSExit x;
+ return aptx_encoder_init_func(state, endian);
+}
+
+__attribute__((no_sanitize("shadow-call-stack")))
+static int aptx_encoder_encode_stereo(void* state, void* pcmL, void* pcmR,
+ void* buffer) {
+ ScopedSCSExit x;
+ return aptx_encoder_encode_stereo_func(state, pcmL, pcmR, buffer);
+}
+
+__attribute__((no_sanitize("shadow-call-stack")))
+static int aptx_encoder_sizeof_params() {
+ ScopedSCSExit x;
+ return aptx_encoder_sizeof_params_func();
+}
+
// offset
#if (BTA_AV_CO_CP_SCMS_T == TRUE)
#define A2DP_APTX_OFFSET (AVDT_MEDIA_OFFSET + 1)
@@ -192,9 +212,9 @@
#endif
a2dp_aptx_encoder_cb.aptx_encoder_state =
- osi_malloc(aptx_encoder_sizeof_params_func());
+ osi_malloc(aptx_encoder_sizeof_params());
if (a2dp_aptx_encoder_cb.aptx_encoder_state != NULL) {
- aptx_encoder_init_func(a2dp_aptx_encoder_cb.aptx_encoder_state, 0);
+ aptx_encoder_init(a2dp_aptx_encoder_cb.aptx_encoder_state, 0);
} else {
LOG_ERROR(LOG_TAG, "%s: Cannot allocate aptX encoder state", __func__);
// TODO: Return an error?
@@ -466,8 +486,8 @@
pcmR[i] = (uint16_t) * (data16_in + ((2 * j) + 1));
}
- aptx_encoder_encode_stereo_func(a2dp_aptx_encoder_cb.aptx_encoder_state,
- &pcmL, &pcmR, &encoded_sample);
+ aptx_encoder_encode_stereo(a2dp_aptx_encoder_cb.aptx_encoder_state, &pcmL,
+ &pcmR, &encoded_sample);
data_out[*data_out_index + 0] = (uint8_t)((encoded_sample[0] >> 8) & 0xff);
data_out[*data_out_index + 1] = (uint8_t)((encoded_sample[0] >> 0) & 0xff);
diff --git a/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc b/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
index fb782dd..d271e0d 100644
--- a/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
@@ -26,6 +26,7 @@
#include "a2dp_vendor.h"
#include "a2dp_vendor_aptx_hd.h"
#include "bt_common.h"
+#include "common/scoped_scs_exit.h"
#include "common/time_util.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -55,6 +56,25 @@
static tAPTX_HD_ENCODER_ENCODE_STEREO aptx_hd_encoder_encode_stereo_func;
static tAPTX_HD_ENCODER_SIZEOF_PARAMS aptx_hd_encoder_sizeof_params_func;
+__attribute__((no_sanitize("shadow-call-stack")))
+static int aptx_hd_encoder_init(void* state, short endian) {
+ ScopedSCSExit x;
+ return aptx_hd_encoder_init_func(state, endian);
+}
+
+__attribute__((no_sanitize("shadow-call-stack")))
+static int aptx_hd_encoder_encode_stereo(void* state, void* pcmL, void* pcmR,
+ void* buffer) {
+ ScopedSCSExit x;
+ return aptx_hd_encoder_encode_stereo_func(state, pcmL, pcmR, buffer);
+}
+
+__attribute__((no_sanitize("shadow-call-stack")))
+static int aptx_hd_encoder_sizeof_params() {
+ ScopedSCSExit x;
+ return aptx_hd_encoder_sizeof_params_func();
+}
+
// offset
#if (BTA_AV_CO_CP_SCMS_T == TRUE)
#define A2DP_APTX_HD_OFFSET (AVDT_MEDIA_OFFSET + 1)
@@ -193,9 +213,9 @@
#endif
a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state =
- osi_malloc(aptx_hd_encoder_sizeof_params_func());
+ osi_malloc(aptx_hd_encoder_sizeof_params());
if (a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state != NULL) {
- aptx_hd_encoder_init_func(a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, 0);
+ aptx_hd_encoder_init(a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, 0);
} else {
LOG_ERROR(LOG_TAG, "%s: Cannot allocate aptX-HD encoder state", __func__);
// TODO: Return an error?
@@ -460,7 +480,7 @@
p += 3;
}
- aptx_hd_encoder_encode_stereo_func(
+ aptx_hd_encoder_encode_stereo(
a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, &pcmL, &pcmR,
&encoded_sample);