stacktrace.cc revision 5222
18839Sandreas.hansson@arm.com/* 28839Sandreas.hansson@arm.com * Copyright .AN) 2007 MIPS Technologies, Inc. All Rights Reserved 38839Sandreas.hansson@arm.com * 48839Sandreas.hansson@arm.com * This software is part of the M5 simulator. 58839Sandreas.hansson@arm.com * 68839Sandreas.hansson@arm.com * THIS IS A LEGAL AGREEMENT. BY DOWNLOADING, USING, COPYING, CREATING 78839Sandreas.hansson@arm.com * DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING 88839Sandreas.hansson@arm.com * TO THESE TERMS AND CONDITIONS. 98839Sandreas.hansson@arm.com * 108839Sandreas.hansson@arm.com * Permission is granted to use, copy, create derivative works and 118839Sandreas.hansson@arm.com * distribute this software and such derivative works for any purpose, 128839Sandreas.hansson@arm.com * so long as (1) the copyright notice above, this grant of permission, 135335Shines@cs.fsu.edu * and the disclaimer below appear in all copies and derivative works 147897Shestness@cs.utexas.edu * made, (2) the copyright notice above is augmented as appropriate to 154486Sbinkertn@umich.edu * reflect the addition of any new copyrightable work in a derivative 164486Sbinkertn@umich.edu * work (e.g., Copyright .AN) <Publication Year> Copyright Owner), and (3) 174486Sbinkertn@umich.edu * the name of MIPS Technologies, Inc. ($B!H(BMIPS$B!I(B) is not used in any 184486Sbinkertn@umich.edu * advertising or publicity pertaining to the use or distribution of 194486Sbinkertn@umich.edu * this software without specific, written prior authorization. 204486Sbinkertn@umich.edu * 214486Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED $B!H(BAS IS.$B!I(B MIPS MAKES NO WARRANTIES AND 224486Sbinkertn@umich.edu * DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR 234486Sbinkertn@umich.edu * OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 244486Sbinkertn@umich.edu * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 254486Sbinkertn@umich.edu * NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE. 264486Sbinkertn@umich.edu * IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, 274486Sbinkertn@umich.edu * INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF 284486Sbinkertn@umich.edu * ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT, 294486Sbinkertn@umich.edu * THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY 304486Sbinkertn@umich.edu * IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR 314486Sbinkertn@umich.edu * STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE 324486Sbinkertn@umich.edu * POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE. 334486Sbinkertn@umich.edu * 344486Sbinkertn@umich.edu * Authors: Nathan L. Binkert 354486Sbinkertn@umich.edu */ 364486Sbinkertn@umich.edu 374486Sbinkertn@umich.edu#include <string> 384486Sbinkertn@umich.edu 394486Sbinkertn@umich.edu#include "arch/mips/isa_traits.hh" 404486Sbinkertn@umich.edu#include "arch/mips/stacktrace.hh" 417897Shestness@cs.utexas.edu#include "arch/mips/vtophys.hh" 428839Sandreas.hansson@arm.com#include "base/bitfield.hh" 434486Sbinkertn@umich.edu#include "base/trace.hh" 446654Snate@binkert.org#include "cpu/base.hh" 456654Snate@binkert.org#include "cpu/thread_context.hh" 466654Snate@binkert.org#include "sim/system.hh" 473102SN/A 483102SN/Ausing namespace std; 496654Snate@binkert.orgusing namespace MipsISA; 502998SN/A 514776Sgblack@eecs.umich.eduProcessInfo::ProcessInfo(ThreadContext *_tc) 524776Sgblack@eecs.umich.edu : tc(_tc) 536654Snate@binkert.org{ 542667SN/A// Addr addr = 0; 554776Sgblack@eecs.umich.edu 564776Sgblack@eecs.umich.edu VirtualPort *vp; 576654Snate@binkert.org 586023Snate@binkert.org vp = tc->getVirtPort(); 598745Sgblack@eecs.umich.edu 606654Snate@binkert.org// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) 616022Sgblack@eecs.umich.edu// panic("thread info not compiled into kernel\n"); 628745Sgblack@eecs.umich.edu// thread_info_size = vp->readGtoH<int32_t>(addr); 636654Snate@binkert.org 646022Sgblack@eecs.umich.edu// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) 658745Sgblack@eecs.umich.edu// panic("thread info not compiled into kernel\n"); 666654Snate@binkert.org// task_struct_size = vp->readGtoH<int32_t>(addr); 676022Sgblack@eecs.umich.edu 688745Sgblack@eecs.umich.edu// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) 696654Snate@binkert.org// panic("thread info not compiled into kernel\n"); 706116Snate@binkert.org// task_off = vp->readGtoH<int32_t>(addr); 718745Sgblack@eecs.umich.edu 726691Stjones1@inf.ed.ac.uk// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) 736691Stjones1@inf.ed.ac.uk// panic("thread info not compiled into kernel\n"); 748745Sgblack@eecs.umich.edu// pid_off = vp->readGtoH<int32_t>(addr); 754486Sbinkertn@umich.edu 765529Snate@binkert.org// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) 771366SN/A// panic("thread info not compiled into kernel\n"); 781310SN/A// name_off = vp->readGtoH<int32_t>(addr); 791310SN/A 802901SN/A tc->delVirtPort(vp); 815712Shsul@eecs.umich.edu} 825529Snate@binkert.org 835529Snate@binkert.orgAddr 845529Snate@binkert.orgProcessInfo::task(Addr ksp) const 855529Snate@binkert.org{ 865529Snate@binkert.org Addr base = ksp & ~0x3fff; 875821Ssaidi@eecs.umich.edu if (base == ULL(0xfffffc0000000000)) 883170SN/A return 0; 895780Ssteve.reinhardt@amd.com 905780Ssteve.reinhardt@amd.com Addr tsk; 915780Ssteve.reinhardt@amd.com 925780Ssteve.reinhardt@amd.com VirtualPort *vp; 935780Ssteve.reinhardt@amd.com 948784Sgblack@eecs.umich.edu vp = tc->getVirtPort(); 958784Sgblack@eecs.umich.edu tsk = vp->readGtoH<Addr>(base + task_off); 968784Sgblack@eecs.umich.edu tc->delVirtPort(vp); 978793Sgblack@eecs.umich.edu 981310SN/A return tsk; 996654Snate@binkert.org} 1006022Sgblack@eecs.umich.edu 1016022Sgblack@eecs.umich.eduint 1028745Sgblack@eecs.umich.eduProcessInfo::pid(Addr ksp) const 1035647Sgblack@eecs.umich.edu{ 1046654Snate@binkert.org Addr task = this->task(ksp); 1056023Snate@binkert.org if (!task) 1066023Snate@binkert.org return -1; 1078745Sgblack@eecs.umich.edu 1085647Sgblack@eecs.umich.edu uint16_t pd; 1096654Snate@binkert.org 1106022Sgblack@eecs.umich.edu VirtualPort *vp; 1116022Sgblack@eecs.umich.edu 1128745Sgblack@eecs.umich.edu vp = tc->getVirtPort(); 1138745Sgblack@eecs.umich.edu pd = vp->readGtoH<uint16_t>(task + pid_off); 1146654Snate@binkert.org tc->delVirtPort(vp); 1156022Sgblack@eecs.umich.edu 1166022Sgblack@eecs.umich.edu return pd; 1178745Sgblack@eecs.umich.edu} 1188745Sgblack@eecs.umich.edu 1196654Snate@binkert.orgstring 1206116Snate@binkert.orgProcessInfo::name(Addr ksp) const 1216116Snate@binkert.org{ 1228745Sgblack@eecs.umich.edu Addr task = this->task(ksp); 1238745Sgblack@eecs.umich.edu if (!task) 1246691Stjones1@inf.ed.ac.uk return "console"; 1256691Stjones1@inf.ed.ac.uk 1266691Stjones1@inf.ed.ac.uk char comm[256]; 1276691Stjones1@inf.ed.ac.uk CopyStringOut(tc, comm, task + name_off, sizeof(comm)); 1288745Sgblack@eecs.umich.edu if (!comm[0]) 1298745Sgblack@eecs.umich.edu return "startup"; 1304997Sgblack@eecs.umich.edu 1314997Sgblack@eecs.umich.edu return comm; 1326654Snate@binkert.org} 1334997Sgblack@eecs.umich.edu 1344997Sgblack@eecs.umich.eduStackTrace::StackTrace() 1351310SN/A : tc(0), stack(64) 1361310SN/A{ 1371310SN/A} 1381310SN/A 1391310SN/AStackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) 1401310SN/A : tc(0), stack(64) 1411310SN/A{ 1421310SN/A trace(_tc, inst); 1433878SN/A} 1443878SN/A 1451310SN/AStackTrace::~StackTrace() 1461369SN/A{ 1471310SN/A} 1481634SN/A 1494167SN/Avoid 1504167SN/AStackTrace::trace(ThreadContext *_tc, bool is_call) 1512998SN/A{ 1524776Sgblack@eecs.umich.edu tc = _tc; 1534776Sgblack@eecs.umich.edu /* FIXME - Jaidev - What is IPR_DTB_CM in Alpha? */ 1548839Sandreas.hansson@arm.com bool usermode = 0; 1558839Sandreas.hansson@arm.com //(tc->readMiscReg(MipsISA::IPR_DTB_CM) & 0x18) != 0; 1568707Sandreas.hansson@arm.com 1578707Sandreas.hansson@arm.com// Addr pc = tc->readNextPC(); 1588756Sgblack@eecs.umich.edu// bool kernel = tc->getSystemPtr()->kernelStart <= pc && 1598707Sandreas.hansson@arm.com// pc <= tc->getSystemPtr()->kernelEnd; 1607876Sgblack@eecs.umich.edu 1618839Sandreas.hansson@arm.com if (usermode) { 1628839Sandreas.hansson@arm.com stack.push_back(user); 1638745Sgblack@eecs.umich.edu return; 1648839Sandreas.hansson@arm.com } 1658839Sandreas.hansson@arm.com 1662998SN/A// if (!kernel) { 1677876Sgblack@eecs.umich.edu// stack.push_back(console); 1687876Sgblack@eecs.umich.edu// return; 1698839Sandreas.hansson@arm.com// } 1707404SAli.Saidi@ARM.com 1717876Sgblack@eecs.umich.edu// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; 1728839Sandreas.hansson@arm.com// Addr ksp = tc->readIntReg(TheISA::StackPointerReg); 1738839Sandreas.hansson@arm.com// Addr bottom = ksp & ~0x3fff; 1748839Sandreas.hansson@arm.com// Addr addr; 1758839Sandreas.hansson@arm.com 1767876Sgblack@eecs.umich.edu// if (is_call) { 1777876Sgblack@eecs.umich.edu// if (!symtab->findNearestAddr(pc, addr)) 1787876Sgblack@eecs.umich.edu// panic("could not find address %#x", pc); 1797876Sgblack@eecs.umich.edu 1807876Sgblack@eecs.umich.edu// stack.push_back(addr); 1817876Sgblack@eecs.umich.edu// pc = tc->readPC(); 1822998SN/A// } 1837868Sgblack@eecs.umich.edu 1842998SN/A// Addr ra; 1852998SN/A// int size; 1862998SN/A 1872998SN/A// while (ksp > bottom) { 1887876Sgblack@eecs.umich.edu// if (!symtab->findNearestAddr(pc, addr)) 1898796Sgblack@eecs.umich.edu// panic("could not find symbol for pc=%#x", pc); 1908796Sgblack@eecs.umich.edu// assert(pc >= addr && "symbol botch: callpc < func"); 1918796Sgblack@eecs.umich.edu 1928796Sgblack@eecs.umich.edu// stack.push_back(addr); 1938796Sgblack@eecs.umich.edu 1948796Sgblack@eecs.umich.edu// if (isEntry(addr)) 1958796Sgblack@eecs.umich.edu// return; 1968796Sgblack@eecs.umich.edu 1978796Sgblack@eecs.umich.edu// if (decodePrologue(ksp, pc, addr, size, ra)) { 1988796Sgblack@eecs.umich.edu// if (!ra) 1998809Sgblack@eecs.umich.edu// return; 2008809Sgblack@eecs.umich.edu 2018809Sgblack@eecs.umich.edu// if (size <= 0) { 2028809Sgblack@eecs.umich.edu// stack.push_back(unknown); 2038809Sgblack@eecs.umich.edu// return; 2042998SN/A// } 2057868Sgblack@eecs.umich.edu 2067868Sgblack@eecs.umich.edu// pc = ra; 2072998SN/A// ksp += size; 2087876Sgblack@eecs.umich.edu// } else { 2092998SN/A// stack.push_back(unknown); 2108839Sandreas.hansson@arm.com// return; 2117876Sgblack@eecs.umich.edu// } 212 213// bool kernel = tc->getSystemPtr()->kernelStart <= pc && 214// pc <= tc->getSystemPtr()->kernelEnd; 215// if (!kernel) 216// return; 217 218// if (stack.size() >= 1000) 219// panic("unwinding too far"); 220// } 221 222// panic("unwinding too far"); 223} 224 225bool 226StackTrace::isEntry(Addr addr) 227{ 228 /* if (addr == tc->readMiscReg(MipsISA::IPR_PALtemp2)) 229 return true;*/ 230 231 return false; 232} 233 234bool 235StackTrace::decodeStack(MachInst inst, int &disp) 236{ 237 // lda $sp, -disp($sp) 238 // 239 // Opcode<31:26> == 0x08 240 // RA<25:21> == 30 241 // RB<20:16> == 30 242 // Disp<15:0> 243 const MachInst mem_mask = 0xffff0000; 244 const MachInst lda_pattern = 0x23de0000; 245 const MachInst lda_disp_mask = 0x0000ffff; 246 247 // subq $sp, disp, $sp 248 // addq $sp, disp, $sp 249 // 250 // Opcode<31:26> == 0x10 251 // RA<25:21> == 30 252 // Lit<20:13> 253 // One<12> = 1 254 // Func<11:5> == 0x20 (addq) 255 // Func<11:5> == 0x29 (subq) 256 // RC<4:0> == 30 257 const MachInst intop_mask = 0xffe01fff; 258 const MachInst addq_pattern = 0x43c0141e; 259 const MachInst subq_pattern = 0x43c0153e; 260 const MachInst intop_disp_mask = 0x001fe000; 261 const int intop_disp_shift = 13; 262 263 if ((inst & mem_mask) == lda_pattern) 264 disp = -sext<16>(inst & lda_disp_mask); 265 else if ((inst & intop_mask) == addq_pattern) 266 disp = -int((inst & intop_disp_mask) >> intop_disp_shift); 267 else if ((inst & intop_mask) == subq_pattern) 268 disp = int((inst & intop_disp_mask) >> intop_disp_shift); 269 else 270 return false; 271 272 return true; 273} 274 275bool 276StackTrace::decodeSave(MachInst inst, int ®, int &disp) 277{ 278 // lda $stq, disp($sp) 279 // 280 // Opcode<31:26> == 0x08 281 // RA<25:21> == ? 282 // RB<20:16> == 30 283 // Disp<15:0> 284 const MachInst stq_mask = 0xfc1f0000; 285 const MachInst stq_pattern = 0xb41e0000; 286 const MachInst stq_disp_mask = 0x0000ffff; 287 const MachInst reg_mask = 0x03e00000; 288 const int reg_shift = 21; 289 290 if ((inst & stq_mask) == stq_pattern) { 291 reg = (inst & reg_mask) >> reg_shift; 292 disp = sext<16>(inst & stq_disp_mask); 293 } else { 294 return false; 295 } 296 297 return true; 298} 299 300/* 301 * Decode the function prologue for the function we're in, and note 302 * which registers are stored where, and how large the stack frame is. 303 */ 304bool 305StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, 306 int &size, Addr &ra) 307{ 308 size = 0; 309 ra = 0; 310 311 for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { 312 MachInst inst; 313 CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); 314 315 int reg, disp; 316 if (decodeStack(inst, disp)) { 317 if (size) { 318 // panic("decoding frame size again"); 319 return true; 320 } 321 size += disp; 322 } else if (decodeSave(inst, reg, disp)) { 323 if (!ra && reg == ReturnAddressReg) { 324 CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); 325 if (!ra) { 326 // panic("no return address value pc=%#x\n", pc); 327 return false; 328 } 329 } 330 } 331 } 332 333 return true; 334} 335 336#if TRACING_ON 337void 338StackTrace::dump() 339{ 340 StringWrap name(tc->getCpuPtr()->name()); 341// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; 342 343 DPRINTFN("------ Stack ------\n"); 344 345// string symbol; 346// for (int i = 0, size = stack.size(); i < size; ++i) { 347// Addr addr = stack[size - i - 1]; 348// if (addr == user) 349// symbol = "user"; 350// else if (addr == console) 351// symbol = "console"; 352// else if (addr == unknown) 353// symbol = "unknown"; 354// else 355// symtab->findSymbol(addr, symbol); 356 357// DPRINTFN("%#x: %s\n", addr, symbol); 358// } 359} 360#endif 361