arch-power.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #include "common/h/Types.h"
00032 #include "common/h/arch-power.h"
00033 using namespace NS_power;
00034 
00035 #if defined(os_vxworks)
00036 #include "common/h/wtxKludges.h"
00037 #endif
00038 
00039 unsigned int NS_power::swapBytesIfNeeded(unsigned int i)
00040 {
00041     static int one = 0x1;
00042 
00043     if ( *((unsigned char *)&one) )
00044         return instruction::swapBytes( *((instructUnion *)&i) ).raw;
00045 
00046     return i;
00047 }
00048 
00049 int instruction::signExtend(unsigned int i, unsigned int pos)
00050 {
00051     int ret;
00052     if (((i >> (--pos)) & 0x1) == 0x1) {
00053         ret = i |  (~0 << pos);
00054     } else {
00055         ret = i & ~(~0 << pos);
00056     }
00057 
00058      return ret;
00059 }
00060 
00061 instructUnion &instruction::swapBytes(instructUnion &i)
00062 {
00063     i.byte[0] = i.byte[0] ^ i.byte[3];
00064     i.byte[3] = i.byte[0] ^ i.byte[3];
00065     i.byte[0] = i.byte[0] ^ i.byte[3];
00066 
00067     i.byte[1] = i.byte[1] ^ i.byte[2];
00068     i.byte[2] = i.byte[1] ^ i.byte[2];
00069     i.byte[1] = i.byte[1] ^ i.byte[2];
00070 
00071     return i;
00072 }
00073 
00074 instruction *instruction::copy() const {
00075     return new instruction(*this);
00076 }
00077 
00078 Address instruction::getTarget(Address addr) const {
00079 #if defined(os_vxworks)
00080     Address ret;
00081     // FIXME requires vxworks in Dyninst
00082     if (relocationTarget(addr, &ret))
00083         return ret;
00084 #endif
00085 
00086     if (isUncondBranch() || isCondBranch()) {
00087         return getBranchOffset() + addr;
00088     }
00089     else if (isInsnType(Bmask, BAAmatch)) // Absolute
00090         return (IFORM_LI(*this) << 2);
00091     else if (isInsnType(Bmask, BCAAmatch)) // Absolute
00092         return (BFORM_BD(*this) << 2);
00093 
00094     return 0;
00095 }
00096 
00097 // TODO: argument _needs_ to be an int, or ABS() doesn't work.
00098 void instruction::setBranchOffset(Address newOffset) {
00099     if (isUncondBranch()) {
00100         assert(ABS((int) newOffset) < MAX_BRANCH);
00101         IFORM_LI_SET(*this, newOffset >> 2);
00102     }
00103     else if (isCondBranch()) {
00104         assert(ABS(newOffset) < MAX_CBRANCH);
00105         BFORM_BD_SET(*this, newOffset >> 2);
00106     }
00107     else {
00108         assert(0);
00109     }
00110 }
00111 
00112 
00113 bool instruction::isCall() const
00114 {
00115 #define CALLmatch 0x48000001 /* bl */
00116     
00117     // Only look for 'bl' instructions for now, although a branch
00118     // could be a call function, and it doesn't need to set the link
00119     // register if it is the last function call
00120     return(isInsnType(OPmask | AALKmask, CALLmatch));
00121 }
00122 
00123 void instruction::setInstruction(codeBuf_t *ptr, Address) {
00124     // We don't need the addr on this platform
00125 
00126     instructUnion *insnPtr = (instructUnion *)ptr;
00127 
00128 #if defined(endian_mismatch)
00129     // Read an instruction from source.  Convert byte order if necessary.
00130     insn_.raw = swapBytesIfNeeded((*insnPtr).raw);
00131 #else
00132     insn_.raw = (*insnPtr).raw;
00133 #endif
00134 }
00135 void instruction::setInstruction(unsigned char *ptr, Address) {
00136     // We don't need the addr on this platform
00137     instructUnion *insnPtr = (instructUnion *)ptr;
00138     insn_ = *insnPtr;
00139 }
00140 
00141 bool instruction::isUncondBranch() const {
00142     return isInsnType(Bmask, Bmatch);
00143 }
00144 
00145 bool instruction::isCondBranch() const {
00146     return isInsnType(Bmask, BCmatch);
00147 }
00148 
00149 unsigned instruction::jumpSize(Address from, Address to, unsigned addr_width) {
00150     Address disp = ABS((long)(to - from));
00151     return jumpSize(disp, addr_width);
00152 }
00153 
00154 // -1 is infinite, don't ya know.
00155 unsigned instruction::jumpSize(Address disp, unsigned addr_width) {
00156    if (ABS(disp) >= MAX_BRANCH) {
00157       return maxInterFunctionJumpSize(addr_width);
00158    }
00159    return instruction::size();
00160 }
00161 
00162 unsigned instruction::maxJumpSize(unsigned addr_width) {
00163    // TODO: some way to do a full-range branch
00164    // For now, a BRL-jump'll do.
00165    // plus two - store r0 and restore afterwards
00166    if (addr_width == 4)
00167       return 30*instruction::size();
00168    else
00169       return 7*instruction::size();
00170 }
00171 
00172 unsigned instruction::maxInterFunctionJumpSize(unsigned addr_width) {
00173    // 4 for 32-bit...
00174    // move <high>, r0
00175    // move <low>, r0
00176    // move r0 -> ctr
00177    // branch to ctr
00178    
00179    // 7 for 64-bit...
00180    // move <top-high>, r0
00181    // move <top-low>, r0
00182    // lshift r0, 32
00183    // move <bot-high>, r0
00184    // move <bot-low>, r0
00185    // move r0 -> ctr
00186    // branch to ctr
00187    if (addr_width == 8)
00188       return 7*instruction::size();
00189    else
00190       return 4*instruction::size();
00191 }
00192 
00193 unsigned instruction::spaceToRelocate() const {
00194 
00195     // We currently assert instead of fixing out-of-range
00196     // branches. In the spirit of "one thing at a time",
00197     // we'll handle that _later_.
00198 
00199     // Actually, since conditional branches have such an abysmally
00200     // short range, we _do_ handle moving them through a complicated
00201     // "jump past an unconditional branch" combo.
00202     
00203   if (isThunk()) {
00204     // Load high; load low; move to LR
00205     return 30*instruction::size();
00206   }
00207   else if (isCondBranch()) {
00208         // Maybe... so worst-case
00209         if ((BFORM_BO(*this) & BALWAYSmask) != BALWAYScond) {
00210             return 3*instruction::size();
00211         }
00212     }
00213     if (isUncondBranch()) {
00214         // Worst case... branch to LR
00215         // and save/restore r0
00216     //
00217     // Upgraded from 6 to 9 for 64-bit
00218         return 9*instruction::size();
00219     }
00220     return instruction::size();
00221 }
00222 
00223 bool instruction::getUsedRegs(pdvector<int> &) {
00224     return false;
00225 }
00226 
00227 // A thunk is a "get PC" operation. We consider
00228 // an instruction to be a thunk if it fulfills the following
00229 // requirements:
00230 //  1) It is unconditional or a "branch always" conditional
00231 //  2) It has an offset of 4
00232 //  3) It saves the return address in the link register
00233 bool instruction::isThunk() const {
00234   switch (BFORM_OP(*this)) {
00235   case Bop:
00236     // Unconditional branch, do nothing
00237     break;
00238   case BCop:
00239     // Must be an "always" condition
00240     if (!(BFORM_BO(*this) & 0x14))
00241       return false;
00242     break;
00243   default:
00244     return false;
00245     break;
00246   }
00247 
00248   // 2
00249   // The displacement is always right shifted 2 (because you can't
00250   // jump to an unaligned address) so we can check if the displacement
00251   // encoded is 1...
00252   if (BFORM_BD(*this) != 1) return false;
00253 
00254   // 3
00255   if (!BFORM_LK(*this)) return false;
00256 
00257   // Oh, and it better not be an absolute...
00258   if (BFORM_AA(*this)) return false;
00259 
00260   return true;
00261 }
00262 
00263 Address instruction::getBranchOffset() const {
00264     if (isUncondBranch()) {
00265         return (IFORM_LI(*this) << 2);
00266     }
00267     else if (isCondBranch()) {
00268         return (BFORM_BD(*this) << 2);
00269     }
00270     return 0;
00271 
00272 }
00273 
00274 unsigned instruction::opcode() const {
00275   return MDFORM_OP(*this);
00276 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1