~ubuntu-branches/ubuntu/karmic/gnash/karmic

« back to all changes in this revision

Viewing changes to libcore/debugger.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack
  • Date: 2008-10-13 14:29:49 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20081013142949-f6qdvnu4mn05ltdc
Tags: 0.8.4~~bzr9980-0ubuntu1
* new upstream release 0.8.4 (LP: #240325)
* ship new lib usr/lib/gnash/libmozsdk.so.* in mozilla-plugin-gnash
  - update debian/mozilla-plugin-gnash.install
* ship new lib usr/lib/gnash/libgnashnet.so.* in gnash-common
  - update debian/gnash-common.install
* add basic debian/build_head script to build latest CVS head packages.
  - add debian/build_head
* new sound architecture requires build depend on libsdl1.2-dev
  - update debian/control
* head build script now has been completely migrated to bzr (upstream +
  ubuntu)
  - update debian/build_head
* disable kde gui until klash/qt4 has been fixed; keep kde packages as empty
  packages for now.
  - update debian/rules
  - debian/klash.install
  - debian/klash.links
  - debian/klash.manpages
  - debian/konqueror-plugin-gnash.install
* drop libkonq5-dev build dependency accordingly
  - update debian/control
* don't install headers manually anymore. gnash doesnt provide a -dev
  package after all
  - update debian/rules
* update libs installed in gnash-common; libgnashserver-*.so is not available
  anymore (removed); in turn we add the new libgnashcore-*.so
  - update debian/gnash-common.install
* use -Os for optimization and properly pass CXXFLAGS=$(CFLAGS) to configure
  - update debian/rules
* touch firefox .autoreg in postinst of mozilla plugin
  - update debian/mozilla-plugin-gnash.postinst
* link gnash in ubufox plugins directory for the plugin alternative switcher
  - add debian/mozilla-plugin-gnash.links
* suggest ubufox accordingly
  - update debian/control
* add new required build-depends on libgif-dev
  - update debian/control
* add Xb-Npp-Description and Xb-Npp-File as new plugin database meta data
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// 
 
2
//   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
3
// 
 
4
// This program is free software; you can redistribute it and/or modify
 
5
// it under the terms of the GNU General Public License as published by
 
6
// the Free Software Foundation; either version 3 of the License, or
 
7
// (at your option) any later version.
 
8
// 
 
9
// This program is distributed in the hope that it will be useful,
 
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
// GNU General Public License for more details.
 
13
// 
 
14
// You should have received a copy of the GNU General Public License
 
15
// along with this program; if not, write to the Free Software
 
16
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 
 
18
#ifdef HAVE_CONFIG_H
 
19
#include "gnashconfig.h"
 
20
#endif
 
21
 
 
22
#include <string>
 
23
#include <sstream>
 
24
#include <map>
 
25
#include <boost/algorithm/string/case_conv.hpp>
 
26
 
 
27
#include "smart_ptr.h" // GNASH_USE_GC
 
28
#include "VM.h"
 
29
#include "rc.h"
 
30
#include "debugger.h"
 
31
#include "log.h"
 
32
#include "as_value.h"
 
33
#include "as_environment.h"
 
34
#include "swf.h"
 
35
#include "ASHandlers.h"
 
36
#include "movie_root.h"
 
37
 
 
38
namespace {
 
39
gnash::RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();
 
40
}
 
41
 
 
42
using namespace std;
 
43
using namespace gnash::SWF;
 
44
 
 
45
namespace gnash 
 
46
{
 
47
 
 
48
const char *as_arg_strs[] = {
 
49
    "ARG_NONE",
 
50
    "ARG_STR",
 
51
    "ARG_HEX",
 
52
    "ARG_U8",
 
53
    "ARG_U16",
 
54
    "ARG_S16",
 
55
    "ARG_PUSH_DATA",
 
56
    "ARG_DECL_DICT",
 
57
    "ARG_FUNCTION2"
 
58
};
 
59
const char *state_strs[] = { "rw", "w", "r" };
 
60
 
 
61
Debugger::Debugger() 
 
62
    : _enabled(false), _tracing(false), _state(NONE), _skipb(0), _env(0), _pc(0)
 
63
{
 
64
//    GNASH_REPORT_FUNCTION;
 
65
}
 
66
 
 
67
Debugger::~Debugger()
 
68
{
 
69
//    GNASH_REPORT_FUNCTION;
 
70
}
 
71
 
 
72
Debugger&
 
73
Debugger::getDefaultInstance()
 
74
{
 
75
        static Debugger dbg;
 
76
        return dbg;
 
77
}
 
78
 
 
79
void
 
80
Debugger::usage()
 
81
{
 
82
//    GNASH_REPORT_FUNCTION;
 
83
    cerr << "Gnash Debugger" << endl;
 
84
    cerr << "\t? - help" << endl;
 
85
    cerr << "\tq - Quit" << endl;
 
86
    cerr << "\tt - Toggle Trace Mode" << endl;
 
87
    cerr << "\tc - Continue" << endl;
 
88
    cerr << "\td - Dissasemble current line" << endl;
 
89
    // info commands
 
90
    cerr << "\ti i - Dump Movie Info" << endl;
 
91
    cerr << "\ti f - Dump Stack Frame" << endl;
 
92
    cerr << "\ti s - Dump symbols" << endl;
 
93
    cerr << "\ti g - Dump Global Regs" << endl;
 
94
    cerr << "\ti r - Dump Local Regs" << endl;
 
95
    cerr << "\ti l - Dump Local Variables" << endl;
 
96
    cerr << "\ti w - Dump watch points" << endl;
 
97
    cerr << "\ti b - Dump break points" << endl;
 
98
    cerr << "\ti c - Dump Function Call Stack" << endl;
 
99
    // break and watch points
 
100
    cerr << "\tw name [r:w:b] - set variable watchpoint" << endl;
 
101
    cerr << "\tw name d - delete variable watchpoint" << endl;
 
102
    cerr << "\tb name [t:f]- enable/disable function break point" << endl;
 
103
    cerr << "\tb name d - delete function break point" << endl;
 
104
    // change data
 
105
    cerr << "\tset var [name] [value] - set a local variable" << endl;
 
106
    cerr << "\tset stack [index] [value] - set a stack entry" << endl;
 
107
    cerr << "\tset reg [index] [value] - set a local register" << endl;
 
108
    cerr << "\tset global [index] [value] - set a global register" << endl;
 
109
}
 
110
 
 
111
void
 
112
Debugger::console()
 
113
{
 
114
//    GNASH_REPORT_FUNCTION;
 
115
    console(*_env);
 
116
}
 
117
 
 
118
// Open a user console for debugging commands. The abbreviations and
 
119
// commands are roughly based on GDBs.
 
120
void
 
121
Debugger::console(as_environment &env)
 
122
{
 
123
//    GNASH_REPORT_FUNCTION;
 
124
 
 
125
    // If the debugger isn't enabled, there is nothing to do.
 
126
    if (!this->isEnabled()) {
 
127
        return;
 
128
    }
 
129
    
 
130
    if (!_env) {
 
131
        cerr << "WARNING: environment not set yet";
 
132
        cerr << "\nOnly watch point commands will work untill after you continue." << endl;
 
133
    }
 
134
//     if (this->isContinuing()) {
 
135
//      this->hitBreak();
 
136
//     } else {
 
137
    string action;
 
138
    string var, val, sstate;
 
139
    int index;
 
140
    Debugger::watch_state_e wstate;
 
141
    bool keep_going = true;
 
142
 
 
143
    log_debug (_("Debugger enabled >> "));
 
144
    while (keep_going) {
 
145
        cerr << "gnashdbg> ";
 
146
        cin >> action;
 
147
        switch (action[0]) {
 
148
            // Quit Gnash.
 
149
          case 'Q':
 
150
          case 'q':
 
151
              exit(0);
 
152
              break;
 
153
              // Continue executing.
 
154
          case 'c':
 
155
              this->go(10);
 
156
              keep_going = false;
 
157
              break;
 
158
              // Change the value of a variable on the stack
 
159
          case 's':
 
160
              if (action == "set") {
 
161
                  cin >> var;
 
162
                  as_value asval;
 
163
                  switch(var[0]) {
 
164
                        // change a parameter on the stack
 
165
                    case 's':
 
166
                        cin >> index >> val;
 
167
                        asval.set_string(val);
 
168
                        this->changeStackValue(index, asval);
 
169
                        break;
 
170
                        // change a local variable
 
171
                    case 'v':
 
172
                        cin >> var >> val;
 
173
                        asval.set_string(val);
 
174
                        this->changeLocalVariable(var, asval);
 
175
                        break;
 
176
                        // change a local register
 
177
                    case 'r':
 
178
                        cin >> index >> val;
 
179
                        asval.set_string(val);
 
180
                        this->changeLocalRegister(index, asval);
 
181
                        break;
 
182
                        // change a global register
 
183
                    case 'g':
 
184
                        cin >> index >> val;
 
185
                        asval.set_string(val);
 
186
                        this->changeGlobalRegister(index, asval);
 
187
                        break;
 
188
                    default:
 
189
                        break;
 
190
                  }
 
191
              }
 
192
              break;
 
193
              // Informational commands.
 
194
          case 'i':
 
195
              cin >> var;
 
196
              switch (var[0]) {
 
197
                case 'd':
 
198
                    this->disassemble();
 
199
                  break;
 
200
                case 'i':
 
201
                    this->dumpMovieInfo();
 
202
                    break;
 
203
                case 'b':
 
204
                    this->dumpBreakPoints();
 
205
                    break;
 
206
                case 'w':
 
207
                    this->dumpWatchPoints();
 
208
                    break;
 
209
                case 'r':
 
210
                    this->dumpLocalRegisters(env);
 
211
                    break;
 
212
                case 'g':
 
213
                    this->dumpGlobalRegisters(env);
 
214
                    break;
 
215
                case 'l':
 
216
                    this->dumpLocalVariables(env);
 
217
                    break;
 
218
                case 'f':
 
219
                    this->dumpStackFrame(env);
 
220
                    break;
 
221
                case 's':
 
222
                    this->dumpSymbols();
 
223
                    break;
 
224
                case 'c':
 
225
                    
 
226
                    this->callStackDump();
 
227
                    break;
 
228
              };
 
229
              break;
 
230
              // Tracing mode. This prints a disasembly every time
 
231
              // Gnash stops at a watch or break point.
 
232
          case 't':
 
233
              if (this->isTracing()) {
 
234
                  this->traceMode(false);
 
235
              } else {
 
236
                  this->traceMode(true);
 
237
              }
 
238
              break;
 
239
              // Print a help screen
 
240
          case '?':
 
241
              this->usage();
 
242
              break;
 
243
              // Set a watchpoint
 
244
          case 'b':
 
245
              cin >> var >> sstate;
 
246
              switch (sstate[0]) {
 
247
                case 't':
 
248
                    this->setBreakPoint(var, true);
 
249
                    break;
 
250
                case 'f':
 
251
                    this->setBreakPoint(var, false);
 
252
                    break;
 
253
                case 'd':
 
254
                    this->removeBreakPoint(var);
 
255
                    break;
 
256
              };
 
257
              break;
 
258
          case 'w':
 
259
              cin >> var >> sstate;
 
260
              switch (sstate[0]) {
 
261
                  // Break on reads
 
262
                case 'r':
 
263
                    wstate = Debugger::READS;
 
264
                    break;
 
265
                    // Break on writes
 
266
                case 'w':
 
267
                    wstate = Debugger::WRITES;
 
268
                    break;
 
269
                    // Break on any accesses
 
270
                case 'b':
 
271
                default:
 
272
                    wstate = Debugger::BOTH;
 
273
                    break;
 
274
              };
 
275
              // Delete a watch point
 
276
              if (sstate[0] == 'd') {
 
277
                  this->removeWatchPoint(var);
 
278
              } else {
 
279
                  this->setWatchPoint(var, wstate);
 
280
              }
 
281
              sstate.erase();
 
282
              break;
 
283
          default:
 
284
              break;
 
285
        };
 
286
    }
 
287
}
 
288
 
 
289
void
 
290
Debugger::callStackDump()
 
291
{
 
292
//    GNASH_REPORT_FUNCTION;
 
293
    vector<string>::const_iterator it;
 
294
    for (it=_callstack.begin(); it!=_callstack.end(); it++) {
 
295
        string str = *it;
 
296
        void *addr = this->lookupSymbol(str);
 
297
        cerr << "\t=> " << *it << "() <" << addr << ">" << endl;
 
298
    }
 
299
}
 
300
 
 
301
void
 
302
Debugger::dumpMovieInfo()
 
303
{
 
304
//    GNASH_REPORT_FUNCTION;
 
305
    if (VM::isInitialized()) {
 
306
        VM& vm = VM::get();
 
307
        movie_root &mr = vm.getRoot();
 
308
        int x, y, buttons;
 
309
        mr.get_mouse_state(x, y, buttons);
 
310
        
 
311
        cerr << "Movie is Flash v" << vm.getSWFVersion() << endl;
 
312
        cerr << "Mouse coordinates are: X=" << x << ", Y=" << y << endl;
 
313
        vm.getGlobal()->dump_members();
 
314
    }
 
315
}
 
316
 
 
317
void
 
318
Debugger::disassemble()
 
319
{
 
320
//    GNASH_REPORT_FUNCTION;
 
321
    this->disassemble(_pc);
 
322
}
 
323
 
 
324
void
 
325
Debugger::disassemble(const unsigned char *data)
 
326
{
 
327
//    GNASH_REPORT_FUNCTION;
 
328
    as_arg_t fmt = ARG_HEX;
 
329
    action_type action_id = static_cast<action_type>(data[0]);
 
330
    int val = 0;
 
331
    string str;
 
332
    unsigned char num[10];
 
333
    memset(num, 0, 10);
 
334
 
 
335
    const gnash::SWF::SWFHandlers& ash = gnash::SWF::SWFHandlers::instance();
 
336
 
 
337
    if (_pc == 0) {
 
338
    }
 
339
    
 
340
    // Show instruction.
 
341
    if (action_id > ash.lastType()) {
 
342
        cerr << "WARNING: <unknown>[0x" << action_id  << "]" << endl;
 
343
    } else {
 
344
        if (ash[action_id].getName().size() > 0) {
 
345
            cerr << "Action: " << (void *)action_id << ": " << ash[action_id].getName().c_str() << endl;
 
346
        } else {
 
347
            cerr << "Action: " << (void *)action_id << ": " << "WARNING: unknown ID" << endl;
 
348
        }
 
349
        fmt = ash[action_id].getArgFormat();
 
350
    }
 
351
 
 
352
    // If we get a ActionPushData opcode, get the parameters
 
353
    if (action_id & 0x80) {
 
354
        int length = data[1] | (data[2] << 8);
 
355
        cerr << "\tArg format is: " << as_arg_strs[fmt] << " Length is: " << length << endl;
 
356
        switch (fmt) {
 
357
          case ARG_NONE:
 
358
              log_error (_("No format flag"));
 
359
              break;
 
360
          case ARG_STR:
 
361
              if ((length == 1) && (data[3] == 0)) {
 
362
                  str = "null";
 
363
              } else {
 
364
                  for (int i = 0; i < length; i++) {
 
365
                      if (data[3 + i] != 0) {
 
366
                          str += data[3 + i];
 
367
                      } else {
 
368
                          break;
 
369
                      }
 
370
                  }
 
371
              }
 
372
              cerr << "Got string (" << length << " bytes): " << "\"" << str << "\"" << endl;
 
373
              break;
 
374
          case ARG_HEX:
 
375
              cerr << hexify((const unsigned char *)&data[3], length, false) << endl;
 
376
              break;
 
377
          case ARG_U8:
 
378
              val = data[3];
 
379
//            cerr << "FIXME: Got u8: " << val << endl;
 
380
              break;
 
381
          case ARG_U16:
 
382
              val = data[3] | (data[4] << 8);
 
383
//            cerr << "FIXME: Got u16: " << val << endl;
 
384
              break;
 
385
          case ARG_S16:
 
386
              val = data[3] | (data[4] << 8);
 
387
              if (val & 0x8000) {
 
388
                  val |= ~0x7FFF;       // sign-extend
 
389
              }
 
390
//            cerr << "FIXME: Got s16: " << val << endl;
 
391
              break;
 
392
          case ARG_PUSH_DATA:
 
393
              break;
 
394
          case ARG_DECL_DICT:
 
395
              break;
 
396
          case ARG_FUNCTION2:
 
397
              break;
 
398
          default:
 
399
              log_error (_("No format flag"));
 
400
              break;
 
401
        } // end of switch(fmt)
 
402
    }
 
403
}
 
404
 
 
405
void
 
406
Debugger::setBreakPoint(const std::string &func, bool enabled)
 
407
{
 
408
//    GNASH_REPORT_FUNCTION;
 
409
    _breakpoints[func] = enabled;
 
410
}
 
411
 
 
412
void
 
413
Debugger::removeBreakPoint(const std::string &func)
 
414
{
 
415
//    GNASH_REPORT_FUNCTION;
 
416
    
 
417
    string name;
 
418
    std::map<std::string, bool>::const_iterator it;
 
419
    it = _breakpoints.find(func);
 
420
    if (it != _breakpoints.end()) {
 
421
        _breakpoints.erase(func);
 
422
    }
 
423
}
 
424
 
 
425
void
 
426
Debugger::dumpBreakPoints()
 
427
{
 
428
//    GNASH_REPORT_FUNCTION;
 
429
    string name;
 
430
    bool val;
 
431
    std::map<std::string, bool>::const_iterator it;
 
432
 
 
433
    int index = 0;
 
434
    for (it=_breakpoints.begin(); it != _breakpoints.end(); it++) {
 
435
        name = it->first;
 
436
        val = it->second;
 
437
        if (name.size()) {
 
438
            string str = (val) ? " is enabled" : " is disabled";
 
439
            cerr << "\tbreak #" << index++ << ": " << name << str << endl;
 
440
        }
 
441
    }
 
442
}
 
443
 
 
444
bool
 
445
Debugger::matchBreakPoint(const std::string &func, bool state)
 
446
{
 
447
//    GNASH_REPORT_FUNCTION;
 
448
    std::map<std::string, bool>::const_iterator it;
 
449
    it =_breakpoints.find(func);
 
450
    if (it == _breakpoints.end()) {
 
451
//      log_debug ("No Match for variable \"%s\"", var);
 
452
        return false;
 
453
    } else {
 
454
        if (state == _breakpoints[func]) {
 
455
//          log_debug ("Matched for Function \"%s\"", func);
 
456
            this->console();
 
457
            return true;
 
458
        }
 
459
        return false;
 
460
    }
 
461
}
 
462
 
 
463
void
 
464
Debugger::setWatchPoint(const std::string &var, watch_state_e state)
 
465
{
 
466
//    GNASH_REPORT_FUNCTION;
 
467
    _watchpoints[var] = state;
 
468
    log_debug (_("Setting watchpoint for variable: \"%s\""), var.c_str());
 
469
}
 
470
 
 
471
void
 
472
Debugger::removeWatchPoint(const std::string &var)
 
473
{
 
474
//    GNASH_REPORT_FUNCTION;
 
475
    
 
476
    string name;
 
477
    std::map<std::string, watch_state_e>::const_iterator it;
 
478
    it = _watchpoints.find(var);
 
479
    if (it != _watchpoints.end()) {
 
480
        _watchpoints.erase(var);
 
481
    }
 
482
}
 
483
 
 
484
void
 
485
Debugger::dumpWatchPoints()
 
486
{
 
487
//    GNASH_REPORT_FUNCTION;
 
488
    string name;
 
489
    watch_state_e state;
 
490
    int index = 0;
 
491
    std::map<std::string, watch_state_e>::const_iterator it;
 
492
    
 
493
    for (it=_watchpoints.begin(); it != _watchpoints.end(); it++) {
 
494
        name = it->first;
 
495
        state = it->second;
 
496
        index++;
 
497
        if (name.size()) {
 
498
            cerr << "\twatch #" << index << ": " << name
 
499
                 << " \"" << state_strs[state] << "\"" << endl;
 
500
        }
 
501
    }
 
502
}
 
503
 
 
504
bool
 
505
Debugger::matchWatchPoint(const std::string &var, watch_state_e state)
 
506
{
 
507
//    GNASH_REPORT_FUNCTION;
 
508
    std::map<std::string, watch_state_e>::const_iterator it;
 
509
    it =_watchpoints.find(var);
 
510
    if (it == _watchpoints.end()) {
 
511
//      log_debug ("No Match for variable \"%s\"", var);
 
512
        return false;
 
513
    } else {
 
514
        if (state == _watchpoints[var]) {
 
515
            log_debug (_("Matched for variable \"%s\": \"%s\""), var.c_str(),
 
516
                       state_strs[state]);
 
517
            this->console();
 
518
            return true;
 
519
        }
 
520
        return false;
 
521
    }
 
522
}
 
523
 
 
524
// These functions manipulate the environment stack
 
525
void
 
526
Debugger::dumpStackFrame()
 
527
{
 
528
//    GNASH_REPORT_FUNCTION;
 
529
    if (_env == 0) {
 
530
        log_error (_("WARNING: environment not set in %s"), __PRETTY_FUNCTION__);
 
531
        return;
 
532
    }
 
533
    this->dumpStackFrame(*_env);
 
534
}
 
535
 
 
536
// Change the value of a parameter on the stack
 
537
void
 
538
Debugger::changeStackValue(unsigned int index, as_value &val)
 
539
{
 
540
//    GNASH_REPORT_FUNCTION;
 
541
    changeStackValue(*_env, index, val);
 
542
}
 
543
 
 
544
void
 
545
Debugger::changeStackValue(as_environment &env, unsigned int index, as_value &val)
 
546
{
 
547
//    GNASH_REPORT_FUNCTION;
 
548
    if (!_env) {
 
549
        log_error (_("WARNING: environment not set in %s"), __PRETTY_FUNCTION__);
 
550
        return;
 
551
    }
 
552
    if (env.stack_size()) {
 
553
        env.bottom(index) = val;
 
554
    }
 
555
}
 
556
 
 
557
void
 
558
Debugger::dumpStackFrame(as_environment &env)
 
559
{
 
560
//    GNASH_REPORT_FUNCTION;    
 
561
    if (!_env) {
 
562
        log_error (_("WARNING: environment not set in %s"), __PRETTY_FUNCTION__);
 
563
        return;
 
564
    }
 
565
    if (env.stack_size()) {
 
566
        log_debug (_("Stack Dump of: %p"), (void *)&env);
 
567
        for (unsigned int i=0, n=env.stack_size(); i<n; i++) {    
 
568
            // FIXME, shouldn't these go to the log as well as to cerr?
 
569
            cerr << "\t" << i << ": ";
 
570
            as_value val = env.bottom(i);
 
571
// FIXME: we want to print the name of the function
 
572
//          if (val.is_as_function()) {
 
573
// //           cerr << val.get_symbol_handle() << endl;
 
574
//              string name = this->lookupSymbol(val.to_object());
 
575
//              if (name.size()) {
 
576
//                  cerr << name << " ";
 
577
//              }
 
578
//          }
 
579
        cerr << env.bottom(i);
 
580
 
 
581
            if (val.is_object()) {
 
582
                boost::intrusive_ptr<as_object> o = val.to_object();
 
583
                string name = lookupSymbol(o.get());
 
584
                if (name.size()) {
 
585
                    cerr << " \"" << name << "\"";
 
586
                }
 
587
#ifndef GNASH_USE_GC
 
588
                cerr << " has #" << o->get_ref_count() << " references";
 
589
#endif
 
590
            }
 
591
            cerr << endl;
 
592
        }
 
593
    }
 
594
    else {
 
595
        log_debug (_("Stack Dump of 0x%p: empty"), (void *)&env);
 
596
    }
 
597
}
 
598
 
 
599
void
 
600
Debugger::dumpLocalRegisters()
 
601
{
 
602
//    GNASH_REPORT_FUNCTION;
 
603
    this->dumpLocalRegisters(*_env);
 
604
}
 
605
 
 
606
void
 
607
Debugger::dumpLocalRegisters(as_environment &env)
 
608
{
 
609
//    GNASH_REPORT_FUNCTION;
 
610
        env.dump_local_registers(cerr);
 
611
}
 
612
 
 
613
void
 
614
Debugger::dumpGlobalRegisters()
 
615
{
 
616
//    GNASH_REPORT_FUNCTION;
 
617
    this->dumpGlobalRegisters(*_env);
 
618
}
 
619
 
 
620
void
 
621
Debugger::dumpGlobalRegisters(as_environment &env)
 
622
{
 
623
//    GNASH_REPORT_FUNCTION;  
 
624
    if (!_env) {
 
625
        log_error (_("WARNING: environment not set in %s"), __PRETTY_FUNCTION__);
 
626
        return;
 
627
    }
 
628
    std::string registers;
 
629
    stringstream ss;
 
630
    log_debug (_("Global Registers Dump:"));
 
631
    for (unsigned int i=0; i<4; ++i) {
 
632
        ss << "\treg #" << i << ": \"";
 
633
        ss << env.global_register(i) << "\"" << endl;
 
634
    }
 
635
    cerr << ss.str().c_str() << endl;
 
636
}
 
637
 
 
638
    // Change the value of a local variable
 
639
void
 
640
Debugger::changeLocalVariable(const std::string &var, as_value &val)
 
641
{
 
642
//    GNASH_REPORT_FUNCTION;
 
643
    changeLocalVariable(*_env, var, val);
 
644
}
 
645
 
 
646
void
 
647
Debugger::changeLocalVariable(as_environment &env, const std::string &var, as_value &val)
 
648
{
 
649
//    GNASH_REPORT_FUNCTION;
 
650
    env.set_local(var, val);
 
651
}
 
652
 
 
653
// Change the value of a local variable
 
654
void
 
655
Debugger::changeLocalRegister(unsigned index, as_value &val)
 
656
{
 
657
//    GNASH_REPORT_FUNCTION;
 
658
    changeLocalRegister(*_env, index, val);
 
659
}
 
660
 
 
661
void
 
662
Debugger::changeLocalRegister(as_environment &env, unsigned index, as_value &val)
 
663
{
 
664
//    GNASH_REPORT_FUNCTION;
 
665
        env.set_local_register(index, val);
 
666
}   
 
667
 
 
668
// Change the value of a global variable
 
669
void
 
670
Debugger::changeGlobalRegister(unsigned index, as_value &val)
 
671
{
 
672
//    GNASH_REPORT_FUNCTION;
 
673
    this->changeLocalRegister(*_env, index, val);
 
674
}
 
675
 
 
676
void
 
677
Debugger::changeGlobalRegister(as_environment &env, unsigned index, as_value &val)
 
678
{
 
679
//    GNASH_REPORT_FUNCTION;
 
680
    env.set_global_register(index, val);
 
681
}   
 
682
 
 
683
void
 
684
Debugger::dumpLocalVariables()
 
685
{
 
686
//    GNASH_REPORT_FUNCTION;
 
687
    this->dumpLocalVariables(*_env);
 
688
}
 
689
 
 
690
void
 
691
Debugger::dumpLocalVariables(as_environment &env)
 
692
{
 
693
        env.dump_local_variables(cerr);
 
694
}
 
695
 
 
696
/// Get the address associated with a name
 
697
void *
 
698
Debugger::lookupSymbol(std::string &name)
 
699
{
 
700
//    GNASH_REPORT_FUNCTION;
 
701
    if (_symbols.size()) {
 
702
        VM& vm = VM::get(); // cache this ?
 
703
        std::string namei = PROPNAME(name);
 
704
        std::map<void *, std::string>::const_iterator it;
 
705
        for (it=_symbols.begin(); it != _symbols.end(); it++) {
 
706
            if (it->second == namei) {
 
707
//              log_debug ("Found symbol %s at address %p", namei.c_str(),
 
708
//                         it->first);
 
709
                return it->first;
 
710
            }
 
711
        }
 
712
    }
 
713
    return NULL; 
 
714
}
 
715
 
 
716
void
 
717
Debugger::addSymbol(void *ptr, std::string name)
 
718
{
 
719
//    GNASH_REPORT_FUNCTION;
 
720
    VM& vm = VM::get(); // cache this ?
 
721
    std::string namei = PROPNAME(name);
 
722
    if (namei.size() > 1)
 
723
    {
 
724
//      log_debug ("Adding symbol %s at address: %p", namei, ptr);
 
725
        _symbols[ptr] = namei;
 
726
    }
 
727
    
 
728
}
 
729
 
 
730
/// Get the name associated with an address
 
731
std::string
 
732
Debugger::lookupSymbol(void *ptr)
 
733
{
 
734
//    GNASH_REPORT_FUNCTION;
 
735
 
 
736
    string str;
 
737
    if (_symbols.size()) {
 
738
        std::map<void *, std::string>::const_iterator it;
 
739
        it = _symbols.find(ptr);
 
740
//      dbglogfile.setStamp(false);
 
741
        if (it != _symbols.end()) {
 
742
//          log_debug ("Found symbol %s at address: %p", it->second.c_str(), ptr);
 
743
            str = it->second;
 
744
//      } else {
 
745
//          log_debug ("No symbol found for address %p", ptr);
 
746
        }
 
747
    }
 
748
//    dbglogfile.setStamp(false);
 
749
    return str;
 
750
}
 
751
 
 
752
void
 
753
Debugger::dumpSymbols()
 
754
{
 
755
//    GNASH_REPORT_FUNCTION;
 
756
    int index = 0;
 
757
    std::map<void *, std::string>::const_iterator it;    
 
758
    for (it=_symbols.begin(); it != _symbols.end(); it++) {
 
759
        string name = it->second;
 
760
        void *addr = it->first;
 
761
        if (name.size()) {
 
762
            cerr << "\tsym #" << index << ": " << name << " <" << addr << ">" << endl;
 
763
        }
 
764
        index++;
 
765
    }
 
766
}
 
767
 
 
768
} // end of gnash namespace
 
769
 
 
770
// Local Variables:
 
771
// mode: C++
 
772
// indent-tabs-mode: t
 
773
// End: