remote_gdb.cc (3536:89aa06409e4d) remote_gdb.cc (3550:515e876568b4)
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 107 unchanged lines hidden (view full) ---

116 * "Stub" to allow remote cpu to debug over a serial line using gdb.
117 */
118
119#include <sys/signal.h>
120
121#include <string>
122#include <unistd.h>
123
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 107 unchanged lines hidden (view full) ---

116 * "Stub" to allow remote cpu to debug over a serial line using gdb.
117 */
118
119#include <sys/signal.h>
120
121#include <string>
122#include <unistd.h>
123
124#include "arch/vtophys.hh"
124#include "arch/alpha/kgdb.h"
125#include "arch/alpha/remote_gdb.hh"
125#include "arch/alpha/remote_gdb.hh"
126#include "arch/vtophys.hh"
126#include "base/intmath.hh"
127#include "base/remote_gdb.hh"
128#include "base/socket.hh"
129#include "base/trace.hh"
130#include "config/full_system.hh"
131#include "cpu/thread_context.hh"
132#include "cpu/static_inst.hh"
133#include "mem/physical.hh"
134#include "mem/port.hh"
135#include "sim/system.hh"
136
137using namespace std;
127#include "base/intmath.hh"
128#include "base/remote_gdb.hh"
129#include "base/socket.hh"
130#include "base/trace.hh"
131#include "config/full_system.hh"
132#include "cpu/thread_context.hh"
133#include "cpu/static_inst.hh"
134#include "mem/physical.hh"
135#include "mem/port.hh"
136#include "sim/system.hh"
137
138using namespace std;
138using namespace AlphaISA;
139using namespace TheISA;
139
140
140RemoteGDB::Event::Event(RemoteGDB *g, int fd, int e)
141 : PollEvent(fd, e), gdb(g)
142{}
143
144void
145RemoteGDB::Event::process(int revent)
146{
147 if (revent & POLLIN)
148 gdb->trap(ALPHA_KENTRY_IF);
149 else if (revent & POLLNVAL)
150 gdb->detach();
151}
152
153RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
141RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
154 : BaseRemoteGDB(_system, c, KGDB_NUMREGS),
155 event(NULL)
156{}
157
158RemoteGDB::~RemoteGDB()
142 : BaseRemoteGDB(_system, c, KGDB_NUMREGS)
159{
143{
160 if (event)
161 delete event;
144 memset(gdbregs.regs, 0, gdbregs.size);
162}
163
164///////////////////////////////////////////////////////////
165// RemoteGDB::acc
166//
167// Determine if the mapping at va..(va+len) is valid.
168//
169bool

--- 94 unchanged lines hidden (view full) ---

264 for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
265 context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]);
266 }
267#endif
268 context->setPC(gdbregs.regs[KGDB_REG_PC]);
269}
270
271void
145}
146
147///////////////////////////////////////////////////////////
148// RemoteGDB::acc
149//
150// Determine if the mapping at va..(va+len) is valid.
151//
152bool

--- 94 unchanged lines hidden (view full) ---

247 for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
248 context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]);
249 }
250#endif
251 context->setPC(gdbregs.regs[KGDB_REG_PC]);
252}
253
254void
272RemoteGDB::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr)
273{
274 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", addr);
275
276 bkpt.address = addr;
277 insertHardBreak(addr, 4);
278}
279
280void
281RemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt)
282{
283 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n",
284 bkpt.address);
285
286
287 removeHardBreak(bkpt.address, 4);
288 bkpt.address = 0;
289}
290
291void
292RemoteGDB::clearSingleStep()
293{
294 DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
255RemoteGDB::clearSingleStep()
256{
257 DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
295 takenBkpt.address, notTakenBkpt.address);
258 takenBkpt, notTakenBkpt);
296
259
297 if (takenBkpt.address != 0)
260 if (takenBkpt != 0)
298 clearTempBreakpoint(takenBkpt);
299
261 clearTempBreakpoint(takenBkpt);
262
300 if (notTakenBkpt.address != 0)
263 if (notTakenBkpt != 0)
301 clearTempBreakpoint(notTakenBkpt);
302}
303
304void
305RemoteGDB::setSingleStep()
306{
307 Addr pc = context->readPC();
308 Addr npc, bpc;

--- 8 unchanged lines hidden (view full) ---

317 if (si->hasBranchTarget(pc, context, bpc)) {
318 // Don't bother setting a breakpoint on the taken branch if it
319 // is the same as the next pc
320 if (bpc != npc)
321 set_bt = true;
322 }
323
324 DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
264 clearTempBreakpoint(notTakenBkpt);
265}
266
267void
268RemoteGDB::setSingleStep()
269{
270 Addr pc = context->readPC();
271 Addr npc, bpc;

--- 8 unchanged lines hidden (view full) ---

280 if (si->hasBranchTarget(pc, context, bpc)) {
281 // Don't bother setting a breakpoint on the taken branch if it
282 // is the same as the next pc
283 if (bpc != npc)
284 set_bt = true;
285 }
286
287 DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
325 takenBkpt.address, notTakenBkpt.address);
288 takenBkpt, notTakenBkpt);
326
289
327 setTempBreakpoint(notTakenBkpt, npc);
290 setTempBreakpoint(notTakenBkpt = npc);
328
329 if (set_bt)
291
292 if (set_bt)
330 setTempBreakpoint(takenBkpt, bpc);
293 setTempBreakpoint(takenBkpt = bpc);
331}
332
333// Write bytes to kernel address space for debugger.
334bool
335RemoteGDB::write(Addr vaddr, size_t size, const char *data)
336{
337 if (BaseRemoteGDB::write(vaddr, size, data)) {
338#ifdef IMB
339 alpha_pal_imb();
340#endif
341 return true;
342 } else {
343 return false;
344 }
345}
346
294}
295
296// Write bytes to kernel address space for debugger.
297bool
298RemoteGDB::write(Addr vaddr, size_t size, const char *data)
299{
300 if (BaseRemoteGDB::write(vaddr, size, data)) {
301#ifdef IMB
302 alpha_pal_imb();
303#endif
304 return true;
305 } else {
306 return false;
307 }
308}
309
347
348PCEventQueue *RemoteGDB::getPcEventQueue()
349{
350 return &system->pcEventQueue;
351}
352
353
354RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
355 : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
356 gdb(_gdb), refcount(0)
357{
358 DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
359}
360
361void
362RemoteGDB::HardBreakpoint::process(ThreadContext *tc)
363{
364 DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
365
366 if (tc == gdb->context)
367 gdb->trap(ALPHA_KENTRY_INT);
368}
369
370bool
371RemoteGDB::insertSoftBreak(Addr addr, size_t len)
372{
373 if (len != sizeof(MachInst))
374 panic("invalid length\n");
375
376 return insertHardBreak(addr, len);
377}
378
379bool
380RemoteGDB::removeSoftBreak(Addr addr, size_t len)
381{
382 if (len != sizeof(MachInst))
383 panic("invalid length\n");
384
385 return removeHardBreak(addr, len);
386}
387
388bool
389RemoteGDB::insertHardBreak(Addr addr, size_t len)
390{
391 if (len != sizeof(MachInst))
392 panic("invalid length\n");
393
394 DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr);
395
396 HardBreakpoint *&bkpt = hardBreakMap[addr];
397 if (bkpt == 0)
398 bkpt = new HardBreakpoint(this, addr);
399
400 bkpt->refcount++;
401
402 return true;
403}
404
405bool
406RemoteGDB::removeHardBreak(Addr addr, size_t len)
407{
408 if (len != sizeof(MachInst))
409 panic("invalid length\n");
410
411 DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr);
412
413 break_iter_t i = hardBreakMap.find(addr);
414 if (i == hardBreakMap.end())
415 return false;
416
417 HardBreakpoint *hbp = (*i).second;
418 if (--hbp->refcount == 0) {
419 delete hbp;
420 hardBreakMap.erase(i);
421 }
422
423 return true;
424}