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 }