13115SN/A/* 24125SN/A * Copyright (c) 2006-2007 The Regents of The University of Michigan 33115SN/A * All rights reserved. 43115SN/A * 53115SN/A * Redistribution and use in source and binary forms, with or without 63115SN/A * modification, are permitted provided that the following conditions are 73115SN/A * met: redistributions of source code must retain the above copyright 83115SN/A * notice, this list of conditions and the following disclaimer; 93115SN/A * redistributions in binary form must reproduce the above copyright 103115SN/A * notice, this list of conditions and the following disclaimer in the 113115SN/A * documentation and/or other materials provided with the distribution; 123115SN/A * neither the name of the copyright holders nor the names of its 133115SN/A * contributors may be used to endorse or promote products derived from 143115SN/A * this software without specific prior written permission. 153115SN/A * 163115SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173115SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183115SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193115SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203115SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213115SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223115SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233115SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243115SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253115SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263115SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273115SN/A * 283115SN/A * Authors: Gabe Black 293115SN/A */ 303115SN/A 313115SN/A#include <sys/ptrace.h> 323115SN/A#include <stdint.h> 333115SN/A 348229Snate@binkert.org#include <cerrno> 358229Snate@binkert.org#include <iostream> 368229Snate@binkert.org 378113Sgblack@eecs.umich.edu#include "arch/sparc/tracechild.hh" 383115SN/A 393115SN/Ausing namespace std; 403115SN/A 418108SN/Abool 428108SN/ASparcTraceChild::sendState(int socket) 434245SN/A{ 444245SN/A uint64_t regVal = 0; 458108SN/A for (int x = 0; x <= I7; x++) { 464245SN/A regVal = getRegVal(x); 478108SN/A if (write(socket, ®Val, sizeof(regVal)) == -1) { 484245SN/A cerr << "Write failed! " << strerror(errno) << endl; 494245SN/A tracing = false; 504245SN/A return false; 514245SN/A } 524245SN/A } 534245SN/A regVal = getRegVal(PC); 548108SN/A if (write(socket, ®Val, sizeof(regVal)) == -1) { 554245SN/A cerr << "Write failed! " << strerror(errno) << endl; 564245SN/A tracing = false; 574245SN/A return false; 584245SN/A } 594245SN/A regVal = getRegVal(NPC); 608108SN/A if (write(socket, ®Val, sizeof(regVal)) == -1) { 614245SN/A cerr << "Write failed! " << strerror(errno) << endl; 624245SN/A tracing = false; 634245SN/A return false; 644245SN/A } 654245SN/A regVal = getRegVal(CCR); 668108SN/A if (write(socket, ®Val, sizeof(regVal)) == -1) { 674245SN/A cerr << "Write failed! " << strerror(errno) << endl; 684245SN/A tracing = false; 694245SN/A return false; 704245SN/A } 714245SN/A return true; 724245SN/A} 734245SN/A 748108SN/Aint64_t 758108SN/AgetRegs(regs & myregs, fpu & myfpu, uint64_t * locals, 768108SN/A uint64_t * inputs, int num) 773115SN/A{ 783115SN/A assert(num < SparcTraceChild::numregs && num >= 0); 798108SN/A switch (num) { 808108SN/A //Global registers 818108SN/A case SparcTraceChild::G0: return 0; 828108SN/A case SparcTraceChild::G1: return myregs.r_g1; 838108SN/A case SparcTraceChild::G2: return myregs.r_g2; 848108SN/A case SparcTraceChild::G3: return myregs.r_g3; 858108SN/A case SparcTraceChild::G4: return myregs.r_g4; 868108SN/A case SparcTraceChild::G5: return myregs.r_g5; 878108SN/A case SparcTraceChild::G6: return myregs.r_g6; 888108SN/A case SparcTraceChild::G7: return myregs.r_g7; 898108SN/A //Output registers 908108SN/A case SparcTraceChild::O0: return myregs.r_o0; 918108SN/A case SparcTraceChild::O1: return myregs.r_o1; 928108SN/A case SparcTraceChild::O2: return myregs.r_o2; 938108SN/A case SparcTraceChild::O3: return myregs.r_o3; 948108SN/A case SparcTraceChild::O4: return myregs.r_o4; 958108SN/A case SparcTraceChild::O5: return myregs.r_o5; 968108SN/A case SparcTraceChild::O6: return myregs.r_o6; 978108SN/A case SparcTraceChild::O7: return myregs.r_o7; 988108SN/A //Local registers 998108SN/A case SparcTraceChild::L0: return locals[0]; 1008108SN/A case SparcTraceChild::L1: return locals[1]; 1018108SN/A case SparcTraceChild::L2: return locals[2]; 1028108SN/A case SparcTraceChild::L3: return locals[3]; 1038108SN/A case SparcTraceChild::L4: return locals[4]; 1048108SN/A case SparcTraceChild::L5: return locals[5]; 1058108SN/A case SparcTraceChild::L6: return locals[6]; 1068108SN/A case SparcTraceChild::L7: return locals[7]; 1078108SN/A //Input registers 1088108SN/A case SparcTraceChild::I0: return inputs[0]; 1098108SN/A case SparcTraceChild::I1: return inputs[1]; 1108108SN/A case SparcTraceChild::I2: return inputs[2]; 1118108SN/A case SparcTraceChild::I3: return inputs[3]; 1128108SN/A case SparcTraceChild::I4: return inputs[4]; 1138108SN/A case SparcTraceChild::I5: return inputs[5]; 1148108SN/A case SparcTraceChild::I6: return inputs[6]; 1158108SN/A case SparcTraceChild::I7: return inputs[7]; 1168108SN/A //Floating point 1178108SN/A case SparcTraceChild::F0: return myfpu.f_fpstatus.fpu_fr[0]; 1188108SN/A case SparcTraceChild::F2: return myfpu.f_fpstatus.fpu_fr[1]; 1198108SN/A case SparcTraceChild::F4: return myfpu.f_fpstatus.fpu_fr[2]; 1208108SN/A case SparcTraceChild::F6: return myfpu.f_fpstatus.fpu_fr[3]; 1218108SN/A case SparcTraceChild::F8: return myfpu.f_fpstatus.fpu_fr[4]; 1228108SN/A case SparcTraceChild::F10: return myfpu.f_fpstatus.fpu_fr[5]; 1238108SN/A case SparcTraceChild::F12: return myfpu.f_fpstatus.fpu_fr[6]; 1248108SN/A case SparcTraceChild::F14: return myfpu.f_fpstatus.fpu_fr[7]; 1258108SN/A case SparcTraceChild::F16: return myfpu.f_fpstatus.fpu_fr[8]; 1268108SN/A case SparcTraceChild::F18: return myfpu.f_fpstatus.fpu_fr[9]; 1278108SN/A case SparcTraceChild::F20: return myfpu.f_fpstatus.fpu_fr[10]; 1288108SN/A case SparcTraceChild::F22: return myfpu.f_fpstatus.fpu_fr[11]; 1298108SN/A case SparcTraceChild::F24: return myfpu.f_fpstatus.fpu_fr[12]; 1308108SN/A case SparcTraceChild::F26: return myfpu.f_fpstatus.fpu_fr[13]; 1318108SN/A case SparcTraceChild::F28: return myfpu.f_fpstatus.fpu_fr[14]; 1328108SN/A case SparcTraceChild::F30: return myfpu.f_fpstatus.fpu_fr[15]; 1338108SN/A case SparcTraceChild::F32: return myfpu.f_fpstatus.fpu_fr[16]; 1348108SN/A case SparcTraceChild::F34: return myfpu.f_fpstatus.fpu_fr[17]; 1358108SN/A case SparcTraceChild::F36: return myfpu.f_fpstatus.fpu_fr[18]; 1368108SN/A case SparcTraceChild::F38: return myfpu.f_fpstatus.fpu_fr[19]; 1378108SN/A case SparcTraceChild::F40: return myfpu.f_fpstatus.fpu_fr[20]; 1388108SN/A case SparcTraceChild::F42: return myfpu.f_fpstatus.fpu_fr[21]; 1398108SN/A case SparcTraceChild::F44: return myfpu.f_fpstatus.fpu_fr[22]; 1408108SN/A case SparcTraceChild::F46: return myfpu.f_fpstatus.fpu_fr[23]; 1418108SN/A case SparcTraceChild::F48: return myfpu.f_fpstatus.fpu_fr[24]; 1428108SN/A case SparcTraceChild::F50: return myfpu.f_fpstatus.fpu_fr[25]; 1438108SN/A case SparcTraceChild::F52: return myfpu.f_fpstatus.fpu_fr[26]; 1448108SN/A case SparcTraceChild::F54: return myfpu.f_fpstatus.fpu_fr[27]; 1458108SN/A case SparcTraceChild::F56: return myfpu.f_fpstatus.fpu_fr[28]; 1468108SN/A case SparcTraceChild::F58: return myfpu.f_fpstatus.fpu_fr[29]; 1478108SN/A case SparcTraceChild::F60: return myfpu.f_fpstatus.fpu_fr[30]; 1488108SN/A case SparcTraceChild::F62: return myfpu.f_fpstatus.fpu_fr[31]; 1498108SN/A //Miscelaneous 1508108SN/A case SparcTraceChild::FSR: return myfpu.f_fpstatus.Fpu_fsr; 1518108SN/A case SparcTraceChild::FPRS: return myregs.r_fprs; 1528108SN/A case SparcTraceChild::PC: return myregs.r_tpc; 1538108SN/A case SparcTraceChild::NPC: return myregs.r_tnpc; 1548108SN/A case SparcTraceChild::Y: return myregs.r_y; 1558108SN/A case SparcTraceChild::CWP: 1568108SN/A return (myregs.r_tstate >> 0) & ((1 << 5) - 1); 1578108SN/A case SparcTraceChild::PSTATE: 1588108SN/A return (myregs.r_tstate >> 8) & ((1 << 13) - 1); 1598108SN/A case SparcTraceChild::ASI: 1608108SN/A return (myregs.r_tstate >> 24) & ((1 << 8) - 1); 1618108SN/A case SparcTraceChild::CCR: 1628108SN/A return (myregs.r_tstate >> 32) & ((1 << 8) - 1); 1638108SN/A default: 1648108SN/A assert(0); 1658108SN/A return 0; 1663115SN/A } 1673115SN/A} 1683115SN/A 1698108SN/Abool 1708108SN/ASparcTraceChild::update(int pid) 1713115SN/A{ 1723115SN/A memcpy(&oldregs, &theregs, sizeof(regs)); 1733115SN/A memcpy(&oldfpregs, &thefpregs, sizeof(fpu)); 1743115SN/A memcpy(oldLocals, locals, 8 * sizeof(uint64_t)); 1753115SN/A memcpy(oldInputs, inputs, 8 * sizeof(uint64_t)); 1768108SN/A if (ptrace(PTRACE_GETREGS, pid, &theregs, 0) != 0) { 1773115SN/A cerr << "Update failed" << endl; 1783115SN/A return false; 1793115SN/A } 1804245SN/A uint64_t stackPointer = getSP(); 1814245SN/A uint64_t stackBias = 2047; 1824245SN/A bool v9 = stackPointer % 2; 1838108SN/A for (unsigned int x = 0; x < 8; x++) { 1844245SN/A uint64_t localAddr = stackPointer + 1854245SN/A (v9 ? (stackBias + x * 8) : (x * 4)); 1864245SN/A locals[x] = ptrace(PTRACE_PEEKTEXT, pid, localAddr, 0); 1878108SN/A if (!v9) locals[x] >>= 32; 1884245SN/A uint64_t inputAddr = stackPointer + 1894245SN/A (v9 ? (stackBias + x * 8 + (8 * 8)) : (x * 4 + 8 * 4)); 1904245SN/A inputs[x] = ptrace(PTRACE_PEEKTEXT, pid, inputAddr, 0); 1918108SN/A if (!v9) inputs[x] >>= 32; 1923115SN/A } 1938108SN/A if (ptrace(PTRACE_GETFPREGS, pid, &thefpregs, 0) != 0) 1943115SN/A return false; 1958108SN/A for (unsigned int x = 0; x < numregs; x++) 1963115SN/A regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x)); 1973115SN/A return true; 1983115SN/A} 1993115SN/A 2003115SN/ASparcTraceChild::SparcTraceChild() 2013115SN/A{ 2028108SN/A for (unsigned int x = 0; x < numregs; x++) 2033115SN/A regDiffSinceUpdate[x] = false; 2043115SN/A} 2053115SN/A 2068108SN/Aint 2078108SN/ASparcTraceChild::getTargets(uint32_t inst, uint64_t pc, uint64_t npc, 2088108SN/A uint64_t &target1, uint64_t &target2) 2094125SN/A{ 2104125SN/A //We can identify the instruction categories we care about using the top 2114125SN/A //10 bits of the instruction, excluding the annul bit in the 3rd most 2124125SN/A //significant bit position and the condition field. We'll call these 2134125SN/A //bits the "sig" for signature. 2144125SN/A uint32_t sig = (inst >> 22) & 0x307; 2154125SN/A uint32_t cond = (inst >> 25) & 0xf; 2164125SN/A bool annul = (inst & (1 << 29)); 2174125SN/A 2184125SN/A //Check if it's a ba... 2194125SN/A bool ba = (cond == 0x8) && 2204125SN/A (sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6); 2214125SN/A //or a bn... 2224125SN/A bool bn = (cond == 0x0) && 2234125SN/A (sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6); 2244125SN/A //or a bcc 2254125SN/A bool bcc = (cond & 0x7) && 2264125SN/A (sig == 0x1 || sig == 0x2 || sig == 0x3 || sig == 0x5 || sig == 0x6); 2274125SN/A 2288108SN/A if (annul) { 2298108SN/A if (bcc) { 2304125SN/A target1 = npc; 2314125SN/A target2 = npc + 4; 2324125SN/A return 2; 23311321Ssteve.reinhardt@amd.com } else if (ba) { 2344125SN/A //This branches immediately to the effective address of the branch 2354125SN/A //which we'll have to calculate. 2364125SN/A uint64_t disp = 0; 2374125SN/A int64_t extender = 0; 2384125SN/A //Figure out how big the displacement field is, and grab the bits 2398108SN/A if (sig == 0x1 || sig == 0x5) { 2404125SN/A disp = inst & ((1 << 19) - 1); 2414125SN/A extender = 1 << 18; 2428108SN/A } else { 2434125SN/A disp = inst & ((1 << 22) - 1); 2444125SN/A extender = 1 << 21; 2454125SN/A } 2464125SN/A //This does sign extension, believe it or not. 2474125SN/A disp = (disp ^ extender) - extender; 2484125SN/A //Multiply the displacement by 4. I'm assuming the compiler is 2494125SN/A //smart enough to turn this into a shift. 2504125SN/A disp *= 4; 2514125SN/A target1 = pc + disp; 25211321Ssteve.reinhardt@amd.com } else if (bn) 2534125SN/A target1 = npc + 4; 2544125SN/A else 2554125SN/A target1 = npc; 2564125SN/A return 1; 2578108SN/A } else { 2584125SN/A target1 = npc; 2594125SN/A return 1; 2604125SN/A } 2614125SN/A} 2624125SN/A 2638108SN/Abool 2648108SN/ASparcTraceChild::step() 2653115SN/A{ 2664125SN/A //Increment the count of the number of instructions executed 2674125SN/A instructions++; 2683115SN/A //Two important considerations are that the address of the instruction 2693115SN/A //being breakpointed should be word (64bit) aligned, and that both the 2703115SN/A //next instruction and the instruction after that need to be breakpointed 2713115SN/A //so that annulled branches will still stop as well. 2723382SN/A 2733382SN/A /* 2743382SN/A * Useful constants 2753382SN/A */ 2763115SN/A const static uint64_t breakInst = 0x91d02001; 2774125SN/A const static uint64_t lowBreakInst = breakInst; 2784125SN/A const static uint64_t highBreakInst = breakInst << 32; 2793115SN/A const static uint64_t breakWord = breakInst | (breakInst << 32); 2803382SN/A const static uint64_t lowMask = 0xFFFFFFFFULL; 2813115SN/A const static uint64_t highMask = lowMask << 32; 2823382SN/A 2833382SN/A /* 2843382SN/A * storage for the original contents of the child process's memory 2853382SN/A */ 2863115SN/A uint64_t originalInst, originalAnnulInst; 2873382SN/A 2883382SN/A /* 2893382SN/A * Get information about where the process is and is headed next. 2903382SN/A */ 2913382SN/A uint64_t currentPC = getRegVal(PC); 2923382SN/A bool unalignedPC = currentPC & 7; 2933382SN/A uint64_t alignedPC = currentPC & (~7); 2943115SN/A uint64_t nextPC = getRegVal(NPC); 2953382SN/A bool unalignedNPC = nextPC & 7; 2963382SN/A uint64_t alignedNPC = nextPC & (~7); 2973382SN/A 2984125SN/A //Get the current instruction 2994125SN/A uint64_t curInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC); 3004125SN/A curInst = unalignedPC ? (curInst & 0xffffffffULL) : (curInst >> 32); 3014125SN/A 3024125SN/A uint64_t bp1, bp2; 3034125SN/A int numTargets = getTargets(curInst, currentPC, nextPC, bp1, bp2); 3044125SN/A assert(numTargets == 1 || numTargets == 2); 3054125SN/A 3064125SN/A bool unalignedBp1 = bp1 & 7; 3074125SN/A uint64_t alignedBp1 = bp1 & (~7); 3084125SN/A bool unalignedBp2 = bp2 & 7; 3094125SN/A uint64_t alignedBp2 = bp2 & (~7); 3104125SN/A uint64_t origBp1, origBp2; 3113382SN/A 3123382SN/A /* 3134125SN/A * Set the first breakpoint 3143382SN/A */ 3154125SN/A origBp1 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp1, 0); 3164125SN/A uint64_t newBp1 = origBp1; 3174125SN/A newBp1 &= unalignedBp1 ? highMask : lowMask; 3184125SN/A newBp1 |= unalignedBp1 ? lowBreakInst : highBreakInst; 3198108SN/A if (ptrace(PTRACE_POKETEXT, pid, alignedBp1, newBp1) != 0) 3204125SN/A cerr << "Poke failed" << endl; 3214125SN/A /* 3224125SN/A * Set the second breakpoint if necessary 3234125SN/A */ 3248108SN/A if (numTargets == 2) { 3254125SN/A origBp2 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp2, 0); 3264125SN/A uint64_t newBp2 = origBp2; 3274125SN/A newBp2 &= unalignedBp2 ? highMask : lowMask; 3284125SN/A newBp2 |= unalignedBp2 ? lowBreakInst : highBreakInst; 3298108SN/A if (ptrace(PTRACE_POKETEXT, pid, alignedBp2, newBp2) != 0) 3303115SN/A cerr << "Poke failed" << endl; 3313115SN/A } 3323382SN/A 3333382SN/A /* 3343382SN/A * Restart the child process 3353382SN/A */ 3363115SN/A //Note that the "addr" parameter is supposed to be ignored, but in at 3373115SN/A //least one version of the kernel, it must be 1 or it will set what 3383115SN/A //pc to continue from 3398108SN/A if (ptrace(PTRACE_CONT, pid, 1, 0) != 0) 3403115SN/A cerr << "Cont failed" << endl; 3413115SN/A doWait(); 3423382SN/A 3433382SN/A /* 3443382SN/A * Update our record of the child's state 3453382SN/A */ 3463115SN/A update(pid); 3473382SN/A 3483382SN/A /* 3494125SN/A * Put back the original contents of the childs address space in the 3504125SN/A * reverse order. 3513382SN/A */ 3528108SN/A if (numTargets == 2) { 3538108SN/A if (ptrace(PTRACE_POKETEXT, pid, alignedBp2, origBp2) != 0) 3544125SN/A cerr << "Poke failed" << endl; 3553115SN/A } 3568108SN/A if (ptrace(PTRACE_POKETEXT, pid, alignedBp1, origBp1) != 0) 3574125SN/A cerr << "Poke failed" << endl; 3583115SN/A} 3593115SN/A 3608108SN/Aint64_t 3618108SN/ASparcTraceChild::getRegVal(int num) 3623115SN/A{ 3633115SN/A return getRegs(theregs, thefpregs, locals, inputs, num); 3643115SN/A} 3653115SN/A 3668108SN/Aint64_t 3678108SN/ASparcTraceChild::getOldRegVal(int num) 3683115SN/A{ 3693115SN/A return getRegs(oldregs, oldfpregs, oldLocals, oldInputs, num); 3703115SN/A} 3713115SN/A 3728108SN/Aostream & 3738108SN/ASparcTraceChild::outputStartState(ostream & os) 3743115SN/A{ 3754125SN/A bool v8 = false; 3763115SN/A uint64_t sp = getSP(); 3778108SN/A if (sp % 2) { 3784125SN/A os << "Detected a 64 bit executable.\n"; 3794125SN/A v8 = false; 3808108SN/A } else { 3814125SN/A os << "Detected a 32 bit executable.\n"; 3824125SN/A v8 = true; 3834125SN/A } 3843115SN/A uint64_t pc = getPC(); 3853115SN/A char obuf[1024]; 3863115SN/A sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp); 3873115SN/A os << obuf; 3883115SN/A sprintf(obuf, "Initial program counter = 0x%016llx\n", pc); 3893115SN/A os << obuf; 3908108SN/A if (!v8) { 3914125SN/A //Take out the stack bias 3924125SN/A sp += 2047; 3934125SN/A } 3943115SN/A //Output the window save area 3958108SN/A for (unsigned int x = 0; x < 16; x++) { 3963115SN/A uint64_t regspot = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 3978108SN/A if (v8) regspot = regspot >> 32; 3983115SN/A sprintf(obuf, "0x%016llx: Window save %d = 0x%016llx\n", 3993115SN/A sp, x+1, regspot); 4003115SN/A os << obuf; 4014125SN/A sp += v8 ? 4 : 8; 4023115SN/A } 4033115SN/A //Output the argument count 4043115SN/A uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 4058108SN/A if (v8) cargc = cargc >> 32; 4063115SN/A sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc); 4073115SN/A os << obuf; 4084125SN/A sp += v8 ? 4 : 8; 4093115SN/A //Output argv pointers 4103115SN/A int argCount = 0; 4113115SN/A uint64_t cargv; 4128108SN/A do { 4133115SN/A cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 4148108SN/A if (v8) cargv = cargv >> 32; 4153115SN/A sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n", 4163115SN/A sp, argCount++, cargv); 4173115SN/A os << obuf; 4184125SN/A sp += v8 ? 4 : 8; 41911321Ssteve.reinhardt@amd.com } while (cargv); 4203115SN/A //Output the envp pointers 4213115SN/A int envCount = 0; 4223115SN/A uint64_t cenvp; 4238108SN/A do { 4243115SN/A cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 4258108SN/A if (v8) cenvp = cenvp >> 32; 4263115SN/A sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n", 4273115SN/A sp, envCount++, cenvp); 4283115SN/A os << obuf; 4294125SN/A sp += v8 ? 4 : 8; 4308108SN/A } while (cenvp); 4313115SN/A uint64_t auxType, auxVal; 4328108SN/A do { 4333115SN/A auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 4348108SN/A if (v8) auxType = auxType >> 32; 4354125SN/A sp += (v8 ? 4 : 8); 4363115SN/A auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 4378108SN/A if (v8) auxVal = auxVal >> 32; 4384125SN/A sp += (v8 ? 4 : 8); 4393115SN/A sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n", 4404125SN/A sp - 8, auxType, auxVal); 4413115SN/A os << obuf; 4428108SN/A } while (auxType != 0 || auxVal != 0); 4433115SN/A //Print out the argument strings, environment strings, and file name. 4443115SN/A string current; 4453115SN/A uint64_t buf; 4463115SN/A uint64_t currentStart = sp; 4473115SN/A bool clearedInitialPadding = false; 4488108SN/A do { 4493115SN/A buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 4503115SN/A char * cbuf = (char *)&buf; 4518108SN/A for (int x = 0; x < sizeof(uint32_t); x++) { 4528108SN/A if (cbuf[x]) 4533115SN/A current += cbuf[x]; 4548108SN/A else { 4553115SN/A sprintf(obuf, "0x%016llx: \"%s\"\n", 4563115SN/A currentStart, current.c_str()); 4573115SN/A os << obuf; 4583115SN/A current = ""; 4593115SN/A currentStart = sp + x + 1; 4603115SN/A } 4613115SN/A } 4624125SN/A sp += (v8 ? 4 : 8); 4633115SN/A clearedInitialPadding = clearedInitialPadding || buf != 0; 4648108SN/A } while (!clearedInitialPadding || buf != 0); 4653115SN/A return os; 4663115SN/A} 4673115SN/A 4688108SN/ATraceChild * 4698108SN/AgenTraceChild() 4703115SN/A{ 4713115SN/A return new SparcTraceChild; 4723115SN/A} 4733115SN/A 474