The Pedigree Project 0.1
x64/StackFrame.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/processor/StackFrame.h"
22#include "pedigree/kernel/processor/state.h"
23#include "pedigree/kernel/processor/types.h"
24
25#include <stdarg.h>
26
27#if DEBUGGER
28
29uintptr_t X64StackFrame::getParameter(size_t n) {
30 if (n == 0)
31 return m_State.rdi;
32 if (n == 1)
33 return m_State.rsi;
34 if (n == 2)
35 return m_State.rdx;
36 if (n == 3)
37 return m_State.rcx;
38 if (n == 4)
39 return m_State.r8;
40 if (n == 5)
41 return m_State.r9;
42
43 uint64_t* pPtr = reinterpret_cast<uint64_t*>(m_State.rbp + (n - 6) * sizeof(uint64_t));
44 return *pPtr;
45}
46
47#endif
48
49void X64StackFrame::construct(ProcessorState& state, uintptr_t returnAddress, unsigned int nParams,
50 ...) {
51 // Align the stack to a 16-byte boundary. SysV AMD64 ABI supplement, Sn
52 // 3.2.2.
53 uintptr_t stack = state.getStackPointer();
54 if (stack & 0xF) {
55 WARNING("StackFrame: given stack was not ABI-compliant, fixing.");
56 stack &= ~0xF;
57 }
58
59 // Obtain the stack pointer.
60 uintptr_t* pStack = reinterpret_cast<uintptr_t*>(stack);
61
62 // How many parameters do we need to push?
63 // We push in reverse order but must iterate through the va_list in forward
64 // order, so we decrement the stack pointer here.
65 ssize_t nToPush = static_cast<ssize_t>(nParams) - 6; // 6 Params can be passed in registers.
66
67 if (nToPush < 0)
68 nToPush = 0;
69 nToPush++; // But we always have to push our return address.
70
71 pStack -= nToPush;
72 uintptr_t* pStackLowWaterMark = pStack;
73
74 *pStack++ = returnAddress;
75
76 va_list list;
77 va_start(list, nParams);
78
79 for (size_t i = 0; i < nParams; i++) {
80 uintptr_t arg = va_arg(list, uintptr_t);
81 switch (i) {
82 case 0:
83 state.rdi = arg;
84 break;
85 case 1:
86 state.rsi = arg;
87 break;
88 case 2:
89 state.rdx = arg;
90 break;
91 case 3:
92 state.rcx = arg;
93 break;
94 case 4:
95 state.r8 = arg;
96 break;
97 case 5:
98 state.r9 = arg;
99 break;
100 default:
101 *pStack++ = arg;
102 }
103 }
104
105 va_end(list);
106
107 // Write the new stack pointer back.
108 state.setStackPointer(reinterpret_cast<uintptr_t>(pStackLowWaterMark));
109}
const ProcessorState & m_State
virtual uintptr_t getParameter(size_t n)