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