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.proc.live; 041 042 import inua.eio.ByteBuffer; 043 import frysk.sys.Errno; 044 import frysk.sys.ProcessIdentifier; 045 import frysk.sys.ptrace.AddressSpace; 046 import frysk.sys.proc.Mem; 047 import frysk.event.Request; 048 import frysk.proc.Manager; 049 050 public class AddressSpaceByteBuffer extends ByteBuffer { 051 protected final AddressSpace addressSpace; 052 protected final ProcessIdentifier pid; 053 054 // Direct files access if possible, or null otherwise. 055 private Mem mem; 056 057 protected AddressSpaceByteBuffer (ProcessIdentifier pid, 058 AddressSpace addressSpace, 059 long lowerExtreem, long upperExtreem) { 060 super (lowerExtreem, upperExtreem); 061 this.pid = pid; 062 this.addressSpace = addressSpace; 063 peekRequest = new PeekRequest(); 064 pokeRequest = new PokeRequest(); 065 if (addressSpace == AddressSpace.TEXT 066 || addressSpace == AddressSpace.DATA) 067 // Try to use /proc; but if any error occures clear it and 068 // revert back to ptrace. 069 mem = new Mem(pid); 070 } 071 public AddressSpaceByteBuffer(ProcessIdentifier pid, 072 AddressSpace addressSpace) { 073 this(pid, addressSpace, 0, addressSpace.length()); 074 } 075 076 077 private class PeekRequest 078 extends Request 079 { 080 private long index; 081 private int value; 082 PeekRequest() 083 { 084 super(Manager.eventLoop); 085 } 086 public void execute () 087 { 088 value = addressSpace.peek(pid, index); 089 } 090 public int request (long index) 091 { 092 if (isEventLoopThread()) 093 return addressSpace.peek(pid, index); 094 else synchronized (this) { 095 this.index = index; 096 request(); 097 return value; 098 } 099 } 100 } 101 private final PeekRequest peekRequest; 102 protected int peek(long index) { 103 return peekRequest.request (index); 104 } 105 106 private class PokeRequest 107 extends Request 108 { 109 private long index; 110 private int value; 111 PokeRequest() 112 { 113 super(Manager.eventLoop); 114 } 115 public void execute () 116 { 117 addressSpace.poke(pid, index, value); 118 } 119 public void request (long index, int value) 120 { 121 if (isEventLoopThread()) 122 addressSpace.poke(pid, index, value); 123 else synchronized (this) { 124 this.index = index; 125 this.value = value; 126 request(); 127 } 128 } 129 } 130 private final PokeRequest pokeRequest; 131 protected void poke(long index, int value) { 132 pokeRequest.request (index, value); 133 } 134 135 private class TransferRequest extends Request { 136 private long index; 137 private byte[] bytes; 138 private int offset; 139 private int length; 140 private boolean write; 141 TransferRequest() { 142 super(Manager.eventLoop); 143 } 144 private void transfer(long index, byte[] bytes, int offset, int length, 145 boolean write) { 146 if (mem != null && !write) { 147 try { 148 mem.pread(index, bytes, offset, length); 149 return; 150 } catch (Errno e) { 151 // Give up on mem; and fall back to ptrace. This 152 // can happen when /proc isn't mounted, or when a 153 // process is terminating and the kernel scrubs 154 // the /proc entry before its time. 155 mem = null; 156 } 157 } 158 addressSpace.transfer(pid, index, bytes, offset, length, 159 write); 160 } 161 162 public void execute() { 163 transfer(index, bytes, offset, length, write); 164 } 165 166 public void request(long index, byte[] bytes, int offset, int length, 167 boolean write) { 168 if (isEventLoopThread()) 169 transfer(index, bytes, offset, length, write); 170 else synchronized (this) { 171 this.index = index; 172 this.bytes = bytes; 173 this.offset = offset; 174 this.length = length; 175 this.write = write; 176 super.request(); 177 } 178 } 179 } 180 private final TransferRequest transfer = new TransferRequest(); 181 182 protected int peek(long index, byte[] bytes, int offset, int length) { 183 transfer.request(index, bytes, offset, length, false); // read 184 return length; 185 } 186 protected int poke(long index, byte[] bytes, int offset, int length) { 187 transfer.request(index, bytes, offset, length, true); // write 188 return length; 189 } 190 191 protected ByteBuffer subBuffer (ByteBuffer parent, long lowerExtreem, 192 long upperExtreem) 193 { 194 AddressSpaceByteBuffer up = (AddressSpaceByteBuffer)parent; 195 return new AddressSpaceByteBuffer (up.pid, up.addressSpace, 196 lowerExtreem, upperExtreem); 197 } 198 }