001    // This file is part of the program FRYSK.
002    //
003    // Copyright 2006, Red Hat Inc.
004    //
005    // FRYSK is free software; you can redistribute it and/or modify it
006    // under the terms of the GNU General Public License as published by
007    // the Free Software Foundation; version 2 of the License.
008    //
009    // FRYSK is distributed in the hope that it will be useful, but
010    // WITHOUT ANY WARRANTY; without even the implied warranty of
011    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012    // General Public License for more details.
013    // 
014    // You should have received a copy of the GNU General Public License
015    // along with FRYSK; if not, write to the Free Software Foundation,
016    // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
017    // 
018    // In addition, as a special exception, Red Hat, Inc. gives You the
019    // additional right to link the code of FRYSK with code not covered
020    // under the GNU General Public License ("Non-GPL Code") and to
021    // distribute linked combinations including the two, subject to the
022    // limitations in this paragraph. Non-GPL Code permitted under this
023    // exception must only link to the code of FRYSK through those well
024    // defined interfaces identified in the file named EXCEPTION found in
025    // the source code files (the "Approved Interfaces"). The files of
026    // Non-GPL Code may instantiate templates or use macros or inline
027    // functions from the Approved Interfaces without causing the
028    // resulting work to be covered by the GNU General Public
029    // License. Only Red Hat, Inc. may make changes or additions to the
030    // list of Approved Interfaces. You must obey the GNU General Public
031    // License in all respects for all of the FRYSK code and other code
032    // used in conjunction with FRYSK except the Non-GPL Code covered by
033    // this exception. If you modify this file, you may extend this
034    // exception to your version of the file, but you are not obligated to
035    // do so. If you do not wish to provide this exception without
036    // modification, you must delete this exception statement from your
037    // version and license this file solely under the GPL without
038    // exception.
039    
040    package frysk.stack;
041    
042    public class FrameIdentifier {
043        private final long functionAddress;
044        private final long cfa;
045        
046        /**
047         * Create a new FrameIdentifier. Identifies a stack frame based on
048         * its canonical frame address and function starting address.
049         * 
050         * @param functionAddress The address of the start of the frame
051         * @param cfa The canonical frame address of the stack frame
052         */
053        public FrameIdentifier (long functionAddress, long cfa) {
054            this.functionAddress = functionAddress;
055            this.cfa = cfa;
056        }
057        
058        /**
059         * Returns true if this FrameIdentifier is inner to the parameter.
060         * 
061         * @param fi  The FrameIdentifier to compare to
062         * @return true If this is inner to fi
063         */
064        public boolean innerTo (FrameIdentifier fi) {
065            return this.cfa < fi.cfa;
066        }
067      
068        /**
069         * Returns true if this FrameIdentifier is outer to the parameter.
070         * 
071         * @param fi  The FrameIdentifier to compare to
072         * @return   true If this is outer to fi
073         */
074        public boolean outerTo (FrameIdentifier fi) {
075            return this.cfa > fi.cfa;
076        }
077        
078        /**
079         * Compares this FrameIdentifier to the parameter and returns true if 
080         * both the cfa and function address match.
081         * 
082         * It is important to use the function address instead of the
083         * stack frame's current address because that address may change
084         * in the lifetime of * a stack frame, and thus this method could
085         * potentially return false if * one of the frames had been
086         * stepped and the other was not. Using the * frame start address
087         * guarantees that if two StackFrames are compared, * and they
088         * both represent the same frame on the stack, this method will *
089         * return true regardless of the state of either frame.
090         * 
091         * @param fi The FrameIdentifier to compare to.
092         * @return true   If the cfa and function address belonging to this
093         * FrameIdentifier match the cfa and function address in the parameter.
094         */
095        public boolean equals (Object fi) {
096            if (! (fi instanceof FrameIdentifier))
097                return false;
098            
099            FrameIdentifier rhs = (FrameIdentifier) fi;
100            return (this.cfa == rhs.cfa
101                    && this.functionAddress == rhs.functionAddress);
102        }
103    
104        /**
105         * Returns the function address from this FrameIdentifier
106         * 
107         * @return functionAddress    The start address of the frame
108         * represented by this FrameIdentifier
109         */
110        public long getFunctionAddress () {
111            return this.functionAddress;
112        }
113      
114        /**
115         * Returns a hashCode for this object
116         */
117        public int hashCode () {
118            return (int) (this.cfa ^ this.functionAddress);
119        }
120      
121        /**
122         * Displays customized String output.
123         */
124        public String toString () {
125            StringBuffer buffer = new StringBuffer();
126            buffer.append("{");
127            buffer.append(super.toString());
128            buffer.append(",functionAddress=");
129            buffer.append(this.functionAddress);
130            buffer.append(",cfa=");
131            buffer.append(this.cfa);
132            buffer.append("}");
133        
134            return buffer.toString();
135        }
136      
137    }