001    // This file is part of the program FRYSK.
002    //
003    // Copyright 2007, 2008, 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.stepping;
041    
042    import frysk.dwfl.ElfSectionCache;
043    import frysk.proc.Task;
044    import lib.dwfl.DwflLine;
045    import lib.dwfl.ElfSectionHeader;
046    
047    public class InstructionStepState extends State {
048    
049        private ElfSectionCache elfCache;
050        private final String PLT_DL_FIXUP = "_dl_fixup";
051    
052        /**
053         * Indicates that this is a step (into) line, if true then plt
054         * entries are skipped.
055         */
056        private final boolean isLine;
057    
058        public InstructionStepState(Task task, boolean isLine) {
059            this.task = task;
060            this.isLine = isLine;
061        }
062    
063        /**
064         * When the instruction observer from SteppingEngine returns, a single
065         * step has been performed. All that is left to do is to reset the State
066         * for this Task back to a StoppedState.
067         * 
068         * @param tse
069         *                The TaskStepEngine for this State.
070         * @return new StoppedState
071         */
072        public State handleUpdate(TaskStepEngine tse) {
073    
074          if (isLine) {
075            long addr = this.task.getPC();
076            this.elfCache = new ElfSectionCache(this.task);
077            ElfSectionHeader header = this.elfCache.getSectionHeader(".plt", addr);
078    
079            /* If the user steps into a function call, the following
080             * catches the .plt section of the program, and ensures that
081             * Frysk steps past it, so that the user is landed back into
082             * their own code after the call. */
083            if (header != null
084                && header.addr <= addr
085                && (header.addr + header.offset) >= addr
086                && (header.type == ElfSectionHeader.ELF_SHT_PROGBITS
087                    || header.type == ElfSectionHeader.ELF_SHT_NOBITS)) {
088    
089                DwflLine line = tse.getDwflLine();
090    
091                if (line == null) {
092                    tse.getSteppingEngine().continueForStepping(this.task, true);
093                    return new InstructionStepThroughState(task, PLT_DL_FIXUP);
094                }
095            }
096          }
097          return new StoppedState(this.task);
098        }
099    
100        public boolean isStopped() {
101            return false;
102        }
103    
104        public boolean isAlive() {
105            return true;
106        }
107    }