2
* Copyright (C) 2009 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
13
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
#include <wtf/Platform.h>
33
#include <MacroAssembler.h>
34
#include <wtf/Noncopyable.h>
40
// This class assists in linking code generated by the macro assembler, once code generation
41
// has been completed, and the code has been copied to is final location in memory. At this
42
// time pointers to labels within the code may be resolved, and relative offsets to external
43
// addresses may be fixed.
46
// * Jump objects may be linked to external targets,
47
// * The address of Jump objects may taken, such that it can later be relinked.
48
// * The return address of a Call may be acquired.
49
// * The address of a Label pointing into the code may be resolved.
50
// * The value referenced by a DataLabel may be set.
52
class LinkBuffer : public Noncopyable {
53
typedef MacroAssemblerCodeRef CodeRef;
54
typedef MacroAssembler::Label Label;
55
typedef MacroAssembler::Jump Jump;
56
typedef MacroAssembler::JumpList JumpList;
57
typedef MacroAssembler::Call Call;
58
typedef MacroAssembler::DataLabel32 DataLabel32;
59
typedef MacroAssembler::DataLabelPtr DataLabelPtr;
62
// Note: Initialization sequence is significant, since executablePool is a PassRefPtr.
63
// First, executablePool is copied into m_executablePool, then the initialization of
64
// m_code uses m_executablePool, *not* executablePool, since this is no longer valid.
65
LinkBuffer(MacroAssembler* masm, PassRefPtr<ExecutablePool> executablePool)
66
: m_executablePool(executablePool)
67
, m_code(masm->m_assembler.executableCopy(m_executablePool.get()))
68
, m_size(masm->m_assembler.size())
80
// These methods are used to link or set values at code generation time.
82
void link(Call call, FunctionPtr function)
84
ASSERT(call.isFlagSet(Call::Linkable));
85
MacroAssembler::linkCall(code(), call, function);
88
void link(Jump jump, CodeLocationLabel label)
90
MacroAssembler::linkJump(code(), jump, label);
93
void link(JumpList list, CodeLocationLabel label)
95
for (unsigned i = 0; i < list.m_jumps.size(); ++i)
96
MacroAssembler::linkJump(code(), list.m_jumps[i], label);
99
void patch(DataLabelPtr label, void* value)
101
MacroAssembler::linkPointer(code(), label.m_label, value);
104
void patch(DataLabelPtr label, CodeLocationLabel value)
106
MacroAssembler::linkPointer(code(), label.m_label, value.executableAddress());
109
// These methods are used to obtain handles to allow the code to be relinked / repatched later.
111
CodeLocationCall locationOf(Call call)
113
ASSERT(call.isFlagSet(Call::Linkable));
114
ASSERT(!call.isFlagSet(Call::Near));
115
return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), call.m_jmp));
118
CodeLocationNearCall locationOfNearCall(Call call)
120
ASSERT(call.isFlagSet(Call::Linkable));
121
ASSERT(call.isFlagSet(Call::Near));
122
return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), call.m_jmp));
125
CodeLocationLabel locationOf(Label label)
127
return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), label.m_label));
130
CodeLocationDataLabelPtr locationOf(DataLabelPtr label)
132
return CodeLocationDataLabelPtr(MacroAssembler::getLinkerAddress(code(), label.m_label));
135
CodeLocationDataLabel32 locationOf(DataLabel32 label)
137
return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), label.m_label));
140
// This method obtains the return address of the call, given as an offset from
141
// the start of the code.
142
unsigned returnAddressOffset(Call call)
144
return MacroAssembler::getLinkerCallReturnOffset(call);
147
// Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called
148
// once to complete generation of the code. 'finalizeCode()' is suited to situations
149
// where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is
150
// suited to adding to an existing allocation.
151
CodeRef finalizeCode()
153
performFinalization();
155
return CodeRef(m_code, m_executablePool, m_size);
157
CodeLocationLabel finalizeCodeAddendum()
159
performFinalization();
161
return CodeLocationLabel(code());
165
// Keep this private! - the underlying code should only be obtained externally via
166
// finalizeCode() or finalizeCodeAddendum().
172
void performFinalization()
175
ASSERT(!m_completed);
179
ExecutableAllocator::makeExecutable(code(), m_size);
180
ExecutableAllocator::cacheFlush(code(), m_size);
183
RefPtr<ExecutablePool> m_executablePool;
193
#endif // ENABLE(ASSEMBLER)
195
#endif // LinkBuffer_h