[arm64] Fix setting up of frame pointer in RegExpMacroAssembler

The frame pointer did not point to the previous frame pointer, which
made the stack non-iterable with SafeStackFrameIterator.

This can cause pointer authentication failures when CFI is enabled,
as we expect the value stored above the previous frame pointer to
be a return address.

Bug: v8:10026
Change-Id: Ia55181038b1b277d0a6df519f1e7f61859847b1a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2614429
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Georgia Kouveli <georgia.kouveli@arm.com>
Cr-Commit-Position: refs/heads/master@{#72036}
This commit is contained in:
Georgia Kouveli 2021-01-11 17:03:41 +00:00 committed by Commit Bot
parent 50a10443f7
commit ec598bbe55
2 changed files with 41 additions and 39 deletions

View File

@ -51,34 +51,35 @@ namespace internal {
*
* The stack will have the following structure:
*
* Location Name Description
* (as referred to in
* the code)
* Location Name Description
* (as referred to
* in the code)
*
* - fp[104] Address regexp Address of the JSRegExp object. Unused in
* native code, passed to match signature of
* the interpreter.
* - fp[96] isolate Address of the current isolate.
* ^^^ sp when called ^^^
* - fp[88] lr Return from the RegExp code.
* - fp[80] r29 Old frame pointer (CalleeSaved).
* - fp[0..72] r19-r28 Backup of CalleeSaved registers.
* - fp[-8] direct_call 1 => Direct call from JavaScript code.
* 0 => Call through the runtime system.
* - fp[-16] stack_base High end of the memory area to use as
* the backtracking stack.
* - fp[-24] output_size Output may fit multiple sets of matches.
* - fp[-32] input Handle containing the input string.
* - fp[-40] success_counter
* - fp[104] Address regexp Address of the JSRegExp object. Unused in
* native code, passed to match signature of
* the interpreter.
* - fp[96] isolate Address of the current isolate.
* ^^^^^^^^^ sp when called ^^^^^^^^^
* - fp[16..88] r19-r28 Backup of CalleeSaved registers.
* - fp[8] lr Return from the RegExp code.
* - fp[0] fp Old frame pointer.
* ^^^^^^^^^ fp ^^^^^^^^^
* - fp[-8] direct_call 1 => Direct call from JavaScript code.
* 0 => Call through the runtime system.
* - fp[-16] stack_base High end of the memory area to use as
* the backtracking stack.
* - fp[-24] output_size Output may fit multiple sets of matches.
* - fp[-32] input Handle containing the input string.
* - fp[-40] success_counter
* ^^^^^^^^^^^^^ From here and downwards we store 32 bit values ^^^^^^^^^^^^^
* - fp[-44] register N Capture registers initialized with
* - fp[-48] register N + 1 non_position_value.
* ... The first kNumCachedRegisters (N) registers
* ... are cached in x0 to x7.
* ... Only positions must be stored in the first
* - ... num_saved_registers_ registers.
* - ...
* - register N + num_registers - 1
* - fp[-44] register N Capture registers initialized with
* - fp[-48] register N + 1 non_position_value.
* ... The first kNumCachedRegisters (N) registers
* ... are cached in x0 to x7.
* ... Only positions must be stored in the first
* - ... num_saved_registers_ registers.
* - ...
* - register N + num_registers - 1
* ^^^^^^^^^ sp ^^^^^^^^^
*
* The first num_saved_registers_ registers are initialized to point to
@ -745,11 +746,10 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
CPURegList argument_registers(x0, x5, x6, x7);
CPURegList registers_to_retain = kCalleeSaved;
registers_to_retain.Combine(fp);
registers_to_retain.Combine(lr);
DCHECK_EQ(registers_to_retain.Count(), kNumCalleeSavedRegisters);
DCHECK(registers_to_retain.IncludesAliasOf(lr));
__ PushCPURegList<TurboAssembler::kSignLR>(registers_to_retain);
__ PushCPURegList<TurboAssembler::kDontStoreLR>(registers_to_retain);
__ Push<TurboAssembler::kSignLR>(lr, fp);
__ PushCPURegList(argument_registers);
// Set frame pointer in place.
@ -1042,9 +1042,10 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
// Set stack pointer back to first register to retain
__ Mov(sp, fp);
__ Pop<TurboAssembler::kAuthLR>(fp, lr);
// Restore registers.
__ PopCPURegList<TurboAssembler::kAuthLR>(registers_to_retain);
__ PopCPURegList<TurboAssembler::kDontLoadLR>(registers_to_retain);
__ Ret();

View File

@ -101,18 +101,19 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64
private:
// Above the frame pointer - Stored registers and stack passed parameters.
// Callee-saved registers x19-x29, where x29 is the old frame pointer.
static const int kCalleeSavedRegisters = 0;
// Return address.
// It is placed above the 11 callee-saved registers.
static const int kReturnAddress =
kCalleeSavedRegisters + 11 * kSystemPointerSize;
static const int kFramePointer = 0;
static const int kReturnAddress = kFramePointer + kSystemPointerSize;
// Callee-saved registers (x19-x28).
static const int kNumCalleeSavedRegisters = 10;
static const int kCalleeSavedRegisters = kReturnAddress + kSystemPointerSize;
// Stack parameter placed by caller.
static const int kIsolate = kReturnAddress + kSystemPointerSize;
// It is placed above the FP, LR and the callee-saved registers.
static const int kIsolate =
kCalleeSavedRegisters + kNumCalleeSavedRegisters * kSystemPointerSize;
// Below the frame pointer.
// Register parameters stored by setup code.
static const int kDirectCall = kCalleeSavedRegisters - kSystemPointerSize;
static const int kDirectCall = -kSystemPointerSize;
static const int kStackBase = kDirectCall - kSystemPointerSize;
static const int kOutputSize = kStackBase - kSystemPointerSize;
static const int kInput = kOutputSize - kSystemPointerSize;