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.
31 #include <MacroAssembler.h>
32 #include <wtf/Noncopyable.h>
38 // This class assists in linking code generated by the macro assembler, once code generation
39 // has been completed, and the code has been copied to is final location in memory. At this
40 // time pointers to labels within the code may be resolved, and relative offsets to external
41 // addresses may be fixed.
44 // * Jump objects may be linked to external targets,
45 // * The address of Jump objects may taken, such that it can later be relinked.
46 // * The return address of a Call may be acquired.
47 // * The address of a Label pointing into the code may be resolved.
48 // * The value referenced by a DataLabel may be set.
50 class LinkBuffer
: public Noncopyable
{
51 typedef MacroAssemblerCodeRef CodeRef
;
52 typedef MacroAssembler::Label Label
;
53 typedef MacroAssembler::Jump Jump
;
54 typedef MacroAssembler::JumpList JumpList
;
55 typedef MacroAssembler::Call Call
;
56 typedef MacroAssembler::DataLabel32 DataLabel32
;
57 typedef MacroAssembler::DataLabelPtr DataLabelPtr
;
60 // Note: Initialization sequence is significant, since executablePool is a PassRefPtr.
61 // First, executablePool is copied into m_executablePool, then the initialization of
62 // m_code uses m_executablePool, *not* executablePool, since this is no longer valid.
63 LinkBuffer(MacroAssembler
* masm
, PassRefPtr
<ExecutablePool
> executablePool
)
64 : m_executablePool(executablePool
)
65 , m_code(masm
->m_assembler
.executableCopy(m_executablePool
.get()))
66 , m_size(masm
->m_assembler
.size())
78 // These methods are used to link or set values at code generation time.
80 void link(Call call
, FunctionPtr function
)
82 ASSERT(call
.isFlagSet(Call::Linkable
));
83 MacroAssembler::linkCall(code(), call
, function
);
86 void link(Jump jump
, CodeLocationLabel label
)
88 MacroAssembler::linkJump(code(), jump
, label
);
91 void link(JumpList list
, CodeLocationLabel label
)
93 for (unsigned i
= 0; i
< list
.m_jumps
.size(); ++i
)
94 MacroAssembler::linkJump(code(), list
.m_jumps
[i
], label
);
97 void patch(DataLabelPtr label
, void* value
)
99 MacroAssembler::linkPointer(code(), label
.m_label
, value
);
102 void patch(DataLabelPtr label
, CodeLocationLabel value
)
104 MacroAssembler::linkPointer(code(), label
.m_label
, value
.executableAddress());
107 // These methods are used to obtain handles to allow the code to be relinked / repatched later.
109 CodeLocationCall
locationOf(Call call
)
111 ASSERT(call
.isFlagSet(Call::Linkable
));
112 ASSERT(!call
.isFlagSet(Call::Near
));
113 return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), call
.m_jmp
));
116 CodeLocationNearCall
locationOfNearCall(Call call
)
118 ASSERT(call
.isFlagSet(Call::Linkable
));
119 ASSERT(call
.isFlagSet(Call::Near
));
120 return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), call
.m_jmp
));
123 CodeLocationLabel
locationOf(Label label
)
125 return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), label
.m_label
));
128 CodeLocationDataLabelPtr
locationOf(DataLabelPtr label
)
130 return CodeLocationDataLabelPtr(MacroAssembler::getLinkerAddress(code(), label
.m_label
));
133 CodeLocationDataLabel32
locationOf(DataLabel32 label
)
135 return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), label
.m_label
));
138 // This method obtains the return address of the call, given as an offset from
139 // the start of the code.
140 unsigned returnAddressOffset(Call call
)
142 return MacroAssembler::getLinkerCallReturnOffset(call
);
145 // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called
146 // once to complete generation of the code. 'finalizeCode()' is suited to situations
147 // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is
148 // suited to adding to an existing allocation.
149 CodeRef
finalizeCode()
151 performFinalization();
153 return CodeRef(m_code
, m_executablePool
, m_size
);
155 CodeLocationLabel
finalizeCodeAddendum()
157 performFinalization();
159 return CodeLocationLabel(code());
163 // Keep this private! - the underlying code should only be obtained externally via
164 // finalizeCode() or finalizeCodeAddendum().
170 void performFinalization()
173 ASSERT(!m_completed
);
177 ExecutableAllocator::makeExecutable(code(), m_size
);
178 ExecutableAllocator::cacheFlush(code(), m_size
);
181 RefPtr
<ExecutablePool
> m_executablePool
;
191 #endif // ENABLE(ASSEMBLER)
193 #endif // LinkBuffer_h