x86/x86_64: cleanup signal trampolines

Let the assembler handle the low-level details of generating .eh_frame,
and use .cfi_escape to output the DWARF3 DW_CFA_def_cfa_expression and
DW_CFA_expression instructions.

Explicitly output a nop instruction between the FDE start
(.cfi_startproc) and the trampoline symbol.

x86_64: remove the rsp instruction, which is redundant with the CFA
itself.

Bug: http://b/169383888
Test: compare `objdump -Wf` output before and after
Test: bionic-unit-tests
Change-Id: Ie2a6d111cb473596be8c9f4fd64534e91d88f2a1
diff --git a/libc/private/bionic_asm_dwarf_exprs.h b/libc/private/bionic_asm_dwarf_exprs.h
new file mode 100644
index 0000000..f988c6e
--- /dev/null
+++ b/libc/private/bionic_asm_dwarf_exprs.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+// Define assembler macros for generating DWARF CFI instructions that use DWARF expressions.
+// Assemblers don't natively support DWARF expressions, so use the C preprocessor and assembler
+// macros to lower them to .cfi_escape directives.
+//
+// Signal trampolines need to use DWARF expressions to record the locations of saved registers,
+// because the offsets from the restored SP to the saved registers is variable. e.g. A signal frame
+// can have optional FP/SIMD extensions, and there may be extra padding if the interrupted SP wasn't
+// aligned.
+
+// DWARF constants.
+#define DW_CFA_def_cfa_expression 0x0f
+#define DW_CFA_expression 0x10
+#define DW_OP_breg0 0x70
+#define DW_OP_deref 0x06
+
+// Return the size of a small uleb128 value: either 1 or 2 bytes
+#define ULEB128_14BIT_SIZE(val) \
+  (1 + (((val) > 0x7f) & 1))
+
+// Return the size of a small sleb128 value: either 1 or 2 bytes
+#define SLEB128_14BIT_SIZE(val)       \
+  (1 + (((val) < -0x40) & 1) +        \
+       (((val) > 0x3f) & 1)     )
+
+// Output a 1 or 2-byte CFI uleb128 absolute value.
+.macro m_cfi_uleb128 val
+  .if (\val) < 0 || (\val) > 0x3fff
+    .error "m_cfi_uleb128 value is out of range (\val)"
+  .elseif (\val) > 0x7f
+    .cfi_escape ((\val) & 0x7f) | 0x80
+    .cfi_escape (\val) >> 7
+  .else
+    .cfi_escape (\val)
+  .endif
+.endm
+
+// Output a 1 or 2-byte CFI sleb128 absolute value.
+.macro m_cfi_sleb128 val
+  .if (\val) < -0x2000 || (\val) > 0x1fff
+    .error "m_cfi_sleb128 value is out of range (\val)"
+  .elseif (\val) < -0x40 || (\val) > 0x3f
+    .cfi_escape ((\val) & 0x7f) | 0x80
+    .cfi_escape ((\val) >> 7) & 0x7f
+  .else
+    .cfi_escape (\val) & 0x7f
+  .endif
+.endm
+
+.macro check_base_reg reg_no
+  .if (\reg_no) < 0 || (\reg_no) > 31
+    .error "base register is out of range for DW_OP_breg0..DW_OP_breg31 (\reg_no)"
+  .endif
+.endm
+
+// Set CFA to the expression, *(base_reg + offset)
+.macro m_cfi_def_cfa_deref base_reg, offset
+  check_base_reg (\base_reg)
+  .cfi_escape DW_CFA_def_cfa_expression
+  m_cfi_uleb128 (1 + SLEB128_14BIT_SIZE(\offset) + 1)   // size of DWARF expression in bytes
+  .cfi_escape DW_OP_breg0 + (\base_reg)                 // expr: 1 byte
+  m_cfi_sleb128 (\offset)                               // expr: 1 or 2 bytes
+  .cfi_escape DW_OP_deref                               // expr: 1 byte
+.endm
+
+// Set the address of the register's previous value to the expression, (base_reg + offset)
+.macro m_cfi_breg_offset dest_reg, base_reg, offset
+  check_base_reg (\base_reg)
+  .cfi_escape DW_CFA_expression
+  m_cfi_uleb128 (\dest_reg)
+  m_cfi_uleb128 (1 + SLEB128_14BIT_SIZE(\offset)) // size of DWARF expression in bytes
+  .cfi_escape DW_OP_breg0 + (\base_reg)           // expr: 1 byte
+  m_cfi_sleb128 (\offset)                         // expr: 1 or 2 bytes
+.endm