001    // This file is part of the program FRYSK.
002    // 
003    // Copyright 2006, 2007, 2008, IBM Corp.
004    // Copyright 2007, 2008, Red Hat Inc.
005    // 
006    // Contributed by
007    // Jose Flavio Aguilar Paulino (joseflavio@gmail.com)
008    // 
009    // FRYSK is free software; you can redistribute it and/or modify it
010    // under the terms of the GNU General Public License as published by
011    // the Free Software Foundation; version 2 of the License.
012    // 
013    // FRYSK is distributed in the hope that it will be useful, but
014    // WITHOUT ANY WARRANTY; without even the implied warranty of
015    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016    // General Public License for more details.
017    // 
018    // You should have received a copy of the GNU General Public License
019    // along with FRYSK; if not, write to the Free Software Foundation,
020    // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
021    // 
022    // In addition, as a special exception, Red Hat, Inc. gives You the
023    // additional right to link the code of FRYSK with code not covered
024    // under the GNU General Public License ("Non-GPL Code") and to
025    // distribute linked combinations including the two, subject to the
026    // limitations in this paragraph. Non-GPL Code permitted under this
027    // exception must only link to the code of FRYSK through those well
028    // defined interfaces identified in the file named EXCEPTION found in
029    // the source code files (the "Approved Interfaces"). The files of
030    // Non-GPL Code may instantiate templates or use macros or inline
031    // functions from the Approved Interfaces without causing the
032    // resulting work to be covered by the GNU General Public
033    // License. Only Red Hat, Inc. may make changes or additions to the
034    // list of Approved Interfaces. You must obey the GNU General Public
035    // License in all respects for all of the FRYSK code and other code
036    // used in conjunction with FRYSK except the Non-GPL Code covered by
037    // this exception. If you modify this file, you may extend this
038    // exception to your version of the file, but you are not obligated to
039    // do so. If you do not wish to provide this exception without
040    // modification, you must delete this exception statement from your
041    // version and license this file solely under the GPL without
042    // exception.
043    
044    package frysk.isa.corefiles;
045    
046    import frysk.sys.ProcessIdentifierFactory;
047    import java.util.Iterator;
048    import inua.eio.ArrayByteBuffer;
049    import inua.eio.ByteBuffer;
050    import lib.dwfl.ElfEHeader;
051    import lib.dwfl.ElfEMachine;
052    import lib.dwfl.ElfNhdr;
053    import lib.dwfl.ElfNhdrType;
054    import lib.dwfl.ElfPrFPRegSet;
055    import lib.dwfl.ElfPrpsinfo;
056    import lib.dwfl.ElfPrstatus;
057    import frysk.isa.registers.PPC32Registers;
058    import frysk.isa.registers.Register;
059    import frysk.isa.banks.BankRegister;
060    import frysk.isa.banks.LinuxPPCRegisterBanks;
061    import frysk.proc.Proc;
062    import frysk.proc.Task;
063    import frysk.sys.proc.CmdLineBuilder;
064    import frysk.sys.proc.Stat;
065    
066    /**
067     * PPC32LinuxElfCorefile. Extends LinuxCorefile. Fill in
068     * specific PPC32 information for corefiles.
069     * 
070     */
071    public class PPC32LinuxElfCorefile extends LinuxElfCorefile {
072    
073        Proc process;
074    
075        Task[] blockedTasks;
076    
077        int size;
078        /**
079         * 
080         * LinuxElfCoreFile. Construct a corefile from a given process, and that process's
081         * tasks that have been blocked.
082         *  
083         * @param process - The parent process to construct the core from.
084         * @param blockedTasks - The process's tasks, in a stopped state
085         */
086        public PPC32LinuxElfCorefile(Proc process, Task blockedTasks[]) {
087            super(process, blockedTasks);
088            this.process = process;
089            this.blockedTasks = blockedTasks;
090            this.size = 32;
091        }
092    
093        /* (non-Javadoc)
094         * @see frysk.util.LinuxElfCorefile#writeNotePrpsinfo(lib.dwfl.ElfNhdr, frysk.proc.Proc)
095         */
096        protected void writeNotePrpsinfo(ElfNhdr nhdrEntry, Proc process) {
097    
098            int pid = process.getPid();
099    
100            ElfPrpsinfo prpsInfo = new ElfPrpsinfo(this.size);
101            Stat processStat = new Stat().scan(ProcessIdentifierFactory.create(pid));
102    
103            // Set state and name.
104            prpsInfo.setPrState(processStat.state);
105            prpsInfo.setPrSname(processStat.state);
106    
107    
108            // If state = Z then set zombie flag
109            if (processStat.state == 'Z')
110                prpsInfo.setPrZomb((char)1);
111            else
112                prpsInfo.setPrZomb((char)0);
113    
114    
115            String midStr = String.valueOf(processStat.nice);
116            prpsInfo.setPrNice(midStr.charAt(0));
117    
118    
119            // Set rest of prpsinfo
120            prpsInfo.setPrFlag(processStat.flags);
121            prpsInfo.setPrUid(process.getUID());
122            prpsInfo.setPrGid(process.getGID());
123    
124            prpsInfo.setPrPid(pid);
125            prpsInfo.setPrPpid(processStat.ppid.intValue());
126            prpsInfo.setPrPgrp(processStat.pgrp);
127    
128            prpsInfo.setPrSid(processStat.session);
129            prpsInfo.setPrFname(processStat.comm);
130    
131            // Build command line
132            class BuildCmdLine extends CmdLineBuilder {
133                String prettyArgs = "";
134    
135                public void buildArgv(String[] argv) {
136    
137                    for (int i = 0; i < argv.length; i++)
138                        prettyArgs += (argv[i] + " ");
139    
140                    // Trim end space
141                    if (prettyArgs.length() > 0)
142                        prettyArgs = prettyArgs.substring(0,
143                                prettyArgs.length() - 1);
144                }
145            }
146            BuildCmdLine cmdLine = new BuildCmdLine();
147            cmdLine.construct(ProcessIdentifierFactory.create(pid));
148    
149            // Set it
150            prpsInfo.setPrPsargs(cmdLine.prettyArgs);
151    
152            // Write entry
153            nhdrEntry.setNhdrDesc(ElfNhdrType.NT_PRPSINFO, prpsInfo);
154        }
155    
156        /* (non-Javadoc)
157         * @see frysk.util.LinuxElfCorefile#writeNotePrstatus(lib.dwfl.ElfNhdr, frysk.proc.Task)
158         */
159        protected void writeNotePrstatus(ElfNhdr nhdrEntry, Task task) {
160    
161            ElfPrstatus prStatus = new ElfPrstatus(this.size);
162    
163            Stat processStat = new Stat().scan(ProcessIdentifierFactory.create(task.getTid()));
164    
165            // Set initial prstatus data
166            prStatus.setPrPid(task.getTid());
167            prStatus.setPrPpid(processStat.ppid.intValue());
168            prStatus.setPrPgrp(processStat.pgrp);
169            prStatus.setPrSid(processStat.session);
170            prStatus.setPrSigPending(processStat.signal);
171    
172            // Order for these registers is found in /usr/include/asm/user.h
173            // This is not the same order that frysk iterators print out, nor
174            // are the names are the same. Create a string[] map to bridge
175            // gap between frysk and core file register order.
176    
177            // The number of total common registers in PPC/PPC64 including nip, msr,
178            // etc. Defined in the asm-ppc/elf.h.
179            Register[] ptracePpcRegMap = { 
180              PPC32Registers.NIP, PPC32Registers.MSR, PPC32Registers.ORIGR3,
181              PPC32Registers.CTR, PPC32Registers.LR, PPC32Registers.XER,
182              PPC32Registers.CCR, PPC32Registers.MQ, PPC32Registers.TRAP,
183              PPC32Registers.DAR, PPC32Registers.DSISR, PPC32Registers.RESULT,
184              PPC32Registers.GPR0, PPC32Registers.GPR1, PPC32Registers.GPR2,
185              PPC32Registers.GPR3, PPC32Registers.GPR4, PPC32Registers.GPR5,
186              PPC32Registers.GPR6, PPC32Registers.GPR7, PPC32Registers.GPR8,
187              PPC32Registers.GPR9, PPC32Registers.GPR10, PPC32Registers.GPR11,
188              PPC32Registers.GPR12, PPC32Registers.GPR13, PPC32Registers.GPR14,
189              PPC32Registers.GPR15, PPC32Registers.GPR16, PPC32Registers.GPR17,
190              PPC32Registers.GPR18, PPC32Registers.GPR19, PPC32Registers.GPR20,
191              PPC32Registers.GPR21, PPC32Registers.GPR22, PPC32Registers.GPR23,
192              PPC32Registers.GPR24, PPC32Registers.GPR25, PPC32Registers.GPR26,
193              PPC32Registers.GPR27, PPC32Registers.GPR28, PPC32Registers.GPR29,
194              PPC32Registers.GPR30, PPC32Registers.GPR31};
195            
196            
197            // Set GP register info
198            int index = 0;
199            int arraySize = 0;
200            int regSize;
201            int wordSize = task.getISA().wordSize();
202            int elfNGREG = 48;
203            
204            // Allocate space in array. Even though there are some registers < wordSize, they still have
205            // to sit in a wordSize area
206            for (int l = 0; l < ptracePpcRegMap.length; l++)
207              if (ptracePpcRegMap[l].getType().getSize() < wordSize)
208                arraySize +=wordSize;
209              else
210                arraySize +=ptracePpcRegMap[l].getType().getSize();
211            
212            int blankRegisterIndex = (elfNGREG - ptracePpcRegMap.length) * wordSize;
213            
214            byte[] byteOrderedRegister= new byte[arraySize+blankRegisterIndex];
215            
216            // Populate array, using wordSize as minimum size
217            for (int i = 0; i < ptracePpcRegMap.length; i++) {
218              regSize = ptracePpcRegMap[i].getType().getSize();
219              if (regSize < wordSize)
220                regSize = wordSize;
221              task.access(ptracePpcRegMap[i], 0, regSize, byteOrderedRegister, index, false);
222              index += regSize;
223            }
224            
225            prStatus.setPrGPRegisterBuffer(byteOrderedRegister);
226            
227            // Write it
228            nhdrEntry.setNhdrDesc(ElfNhdrType.NT_PRSTATUS, prStatus);
229        }
230    
231        /*
232             * (non-Javadoc)
233             * 
234             * @see frysk.util.LinuxElfCorefile#writeNoteFPRegset(lib.dwfl.ElfNhdr,
235             *      frysk.proc.Task)
236             */
237        protected void writeNoteFPRegset(ElfNhdr nhdrEntry, Task task) {
238            
239            ElfPrFPRegSet xfpRegSet = new ElfPrFPRegSet();
240            
241            final int bankSize = 260;
242            final int maxRegSize = 8;
243            byte[] scratch = new byte[maxRegSize];
244            byte[] byteOrderedRegister= new byte[bankSize];
245            ArrayByteBuffer byteOrderedBuffer = new ArrayByteBuffer(byteOrderedRegister);
246            
247            Iterator registerIterator =  LinuxPPCRegisterBanks.FPREGS32.entryIterator();
248            while (registerIterator.hasNext()) {
249                BankRegister bankRegister = ((BankRegister)registerIterator.next());
250                Register register = bankRegister.getRegister();
251                task.access(register, 0, register.getType().getSize(), scratch, 0, false);
252                bankRegister.access(byteOrderedBuffer, 0, maxRegSize, scratch, 0, true);
253            }
254            
255            byteOrderedBuffer.get(byteOrderedRegister);
256            
257            xfpRegSet.setFPRegisterBuffer(byteOrderedRegister);
258            
259            // Write it
260            nhdrEntry.setNhdrDesc(ElfNhdrType.NT_FPREGSET, xfpRegSet);
261    
262            ElfPrFPRegSet fpRegSet = new ElfPrFPRegSet();
263    
264            // Write FP Register info over wholesae. Do not interpret.
265            ByteBuffer registerMaps[] = task.getRegisterBuffersFIXME();
266            byte[] regBuffer = new byte[(int) registerMaps[1].capacity()];
267            registerMaps[1].get(regBuffer);
268    
269            fpRegSet.setFPRegisterBuffer(regBuffer);
270    
271            // Write it
272            nhdrEntry.setNhdrDesc(ElfNhdrType.NT_FPREGSET, fpRegSet);
273        }
274    
275        /* (non-Javadoc)
276         * @see frysk.util.LinuxElfCorefile#writeNotePRXFPRegset(lib.dwfl.ElfNhdr, frysk.proc.Task)
277         */
278        protected boolean writeNotePRXFPRegset(ElfNhdr nhdrEntry, Task task) {
279            return false;
280        }
281    
282        /* (non-Javadoc)
283         * @see frysk.util.LinuxElfCorefile#getElfMachineType()
284         */
285        protected byte getElfMachineType() {
286            return ElfEMachine.EM_PPC;
287        }
288    
289        /* (non-Javadoc)
290         * @see frysk.util.LinuxElfCorefile#getElfMachineClass()
291         */
292        protected byte getElfMachineClass() {
293            return ElfEHeader.CLASS32;
294        }
295    }