Package: kdbg Version: 2.5.0-1 Severity: important I'm trying to debug a program that uses the SpiderMonkey JavaScript engine - I don't know if this is a factor.
I will attach the program itself. You compile it with g++ -O0 -g -Wall -o sudoku-solver $(pkg-config --cflags mozilla-js) \ $(pkg-config --libs mozilla-js) sudoku-solver.cpp When you run kdbg sudoku-solver You will notice that the startup takes ages. I'm using KDE Trinity so I can launch system guard and it tells me that gdb is really busy. After a few minutes kdbg finally shows the source code. I have kdbg configured to hide itself until it hits a breakpoint or exception. Set a breakpoint at line 763, 'cout << "Values";' When you tell it to run, it minimizes for a few minutes until it hits the breakpoint in what is a really trivial program that should be instantaneous. The time kdbg takes seems to increase the more you restart it. -- System Information: Debian Release: wheezy/sid APT prefers testing APT policy: (500, 'testing'), (500, 'stable') Architecture: amd64 (x86_64) Kernel: Linux 2.6.38-2-amd64 (SMP w/2 CPU cores) Locale: LANG=en_IE.UTF-8, LC_CTYPE=en_IE.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages kdbg depends on: ii kdebase-runtime 4:4.4.5-1 runtime components from the offici ii libc6 2.13-4 Embedded GNU C Library: Shared lib ii libgcc1 1:4.6.0-2 GCC support library ii libkdecore5 4:4.4.5-5 the KDE Platform Core Library ii libkdeui5 4:4.4.5-5 the KDE Platform User Interface Li ii libkio5 4:4.4.5-5 the Network-enabled File Managemen ii libqt4-dbus 4:4.7.3-1 Qt 4 D-Bus module ii libqt4-network 4:4.7.3-1 Qt 4 network module ii libqt4-svg 4:4.7.3-1 Qt 4 SVG module ii libqt4-xml 4:4.7.3-1 Qt 4 XML module ii libqtcore4 4:4.7.3-1 Qt 4 core module ii libqtgui4 4:4.7.3-1 Qt 4 GUI module ii libstdc++6 4.6.0-2 The GNU Standard C++ Library v3 Versions of packages kdbg recommends: ii gdb 7.2-1 The GNU Debugger kdbg suggests no packages. -- no debconf information
// Copyright (C) 2011 Philip Ashmore ([email protected]) // License: LGPLv3. See LICENSE.txt for the full license. // (libc.info.gz)Memory-mapped I/O // https://developer.mozilla.org/En/SpiderMonkey/JSAPI_User_Guide // Release mode // g++ -O3 -g -Wall -o sudoku-solver $(pkg-config --cflags mozilla-js) $(pkg-config --libs mozilla-js) sudoku-solver.cpp // Debug mode // g++ -O0 -g -Wall -o sudoku-solver $(pkg-config --cflags mozilla-js) $(pkg-config --libs mozilla-js) sudoku-solver.cpp #include <sys/types.h> #include <sys/mman.h> #include <ftw.h> #include <fcntl.h> #include <string.h> #include <iostream> #include <iomanip> #include <map> #include <set> using namespace std; #include <jsapi.h> typedef map< string, uintN > SolutionsMap; SolutionsMap solutions; string last_text, puzzle; uint64_t permute_count = 0; uint64_t solution_count = 0; bool g_all = false, g_quiet = false; namespace Sudoku { class BoardItem { public: BoardItem(uintN n = 0) : m_data(n) {} BoardItem & operator =(uintN x) { set_number(x, false); return *this; } uintN number() const { return m_data & 15; } bool given() const { return m_data & 16; } void set_number(uintN num, bool given_) { m_data = num + (given_ ? 16 : 0); } void set_given(bool b) { m_data = number() + (b ? 16 : 0); } operator uintN() const { return number(); } protected: uintN m_data; }; typedef BoardItem Board[9][9]; struct Row { Row() : m_data() { for(uintN n = 0; n < 9; ++n) m_data[n] = BoardItem(); } Row(const Row & o) : m_data(o.m_data) { for(uintN n = 0; n < 9; ++n) m_data[n] = o.m_data[n]; } Row & operator =(const Row & o) { for(uintN n = 0; n < 9; ++n) m_data[n] = o.m_data[n]; return *this; } BoardItem & operator[](uintN n) { return m_data[n]; } const BoardItem & operator[](uintN n) const { return m_data[n]; } bool empty() const { uintN n; for(n = 0; n < 9; ++n) if(m_data[n]) return false; return true; } inline uintN length() const { uintN n; for(n = 0; n < 9; ++n) if(!m_data[n]) break; return n; } protected: BoardItem m_data[9]; }; ostream & operator <<(ostream & s, const Row & r) { uintN len = r.length(); for(uintN n = 0; n < len; ++n) { if(n) s << ' '; s << r[n]; } return s; } struct stream_range { stream_range(const Row & r_, uintN m_) : row(r_) , mark(m_) {} const Row & row; uintN mark; }; ostream & operator <<(ostream & s, const stream_range & r) { uintN len = r.row.length(); for(uintN n = 0; n < len; ++n) { if(n) s << ' '; if(n == r.mark) s << '['; s << r.row[n]; if(n == r.mark) s << ']'; } return s; } const Row row_all_filled() { Row r; for(uintN n = 0; n < 9; ++n) r[n] = n + 1; return r; } const Row all_filled = row_all_filled(); class Solver { public: Solver() : m_board() {} virtual ~Solver() {} virtual uint64_t count() = 0; Board m_board; }; template< bool all, bool quiet > class SolverT : public Solver { public: SolverT() : Solver() {} Row filter_by_row(uintN x0, uintN y0, const Row & a0) { Row a1; uintN a, x; for(a = 0; a < 9; ++a) { if(!a0[a]) continue; for(x = 0; x < 9; ++x) { if(x == x0) continue; if(m_board[x][y0] == a) break; } if(x != 9) continue; a1[a] = a + 1; } //cout << "filter_by_row[" << x0 << ", " << y0 << "] returning [" << a1 // << ']' << endl; return a1; } Row filter_by_column(uintN x0, uintN y0, const Row & a0) { Row a1; uintN a, y; for(a = 0; a < 9; ++a) { if(!a0[a]) continue; for(y = 0; y < 9; ++y) { if(y == y0) continue; if(m_board[x0][y] == a) break; } if(y != 9) continue; a1[a] = a + 1; } //cout << "filter_by_column[" << x0 << ", " << y0 << "] returning [" << a1 // << ']' << endl; return a1; } Row filter_by_grid(uintN x0, uintN y0, const Row & a0) { Row a1; uintN a, x, y, gx = (x0/3)*3, gy = (y0/3)*3; for(a = 0; a < 9; ++a) { if(!a0[a]) continue; for(x = gx; x < (gx + 3); ++x) { for(y = gy; y < (gy + 3); ++y) { if((x == x0) && (y == y0)) continue; if(m_board[x][y] == a) break; } if(y != (gy + 3)) break; } if(x != (gx + 3)) continue; a1[a] = a + 1; } //cout << "filter_by_grid[" << x0 << ", " << y0 << "] returning [" << a1 // << ']' << endl; return a1; } struct BlankFinderResult { BlankFinderResult(uintN x_ = 0, uintN y_ = 0, bool g_ = false) : x(x_), y(y_), good(g_) {} uintN x, y; bool good; }; BlankFinderResult first_blank(uintN x0, uintN y0) { uintN xn = x0; for(uintN y = y0; y < 9; ++y) { for(uintN x = xn; x < 9; ++x) { if(!m_board[x][y]) return BlankFinderResult(x, y, true); } xn = 0; } return BlankFinderResult(0, 0, false); } BlankFinderResult next_blank(uintN x, uintN y) { if(x == 8) { if(y == 8) return BlankFinderResult(0, 0, false); return first_blank(0, y+1); } return first_blank(x+1, y); } void permute_square(uintN level, uintN x, uintN y) { if(all) { if(!quiet) { ++permute_count; if(!(permute_count % 10000000)) { cout << "#solutions " << solution_count << "\n==================\n"; dump_solution(); } } } // Iterate through the valid entries for this square. // If there are no valid entries then we're sunk. Row range = filter_by_grid(x,y , filter_by_row(x,y , filter_by_column(x,y, all_filled))); uintN rl = range.length(); if(!rl) { //cout << '[' << setw(2) << level << "] no solutions possible\n" //"==========================\n"; //dump_solution(); return; // No solutions possible. } uintN a; if(!level) { //this.worker.postMessage({ cmd : "range", value : range.length }); //this.worker.postMessage({ cmd : "update", value : 0 }); ; } for(a = 0; a < rl; ++a) { //for(uintN i = 0; i < level; ++i) // cout << " "; //cout << "[" << (x+1) << ", " << (y+1) << "] " // << "-> " << stream_range(range, a) << endl; if(!level) ; //this.worker.postMessage({ cmd : "update", value : a }); m_board[x][y] = range[a]; //this.report(); BlankFinderResult ret = next_blank(x, y); if(!ret.good) { ++solution_count; if(!quiet) { if(all) { if(!(solution_count % 100000)) cout << '.' << flush; }else{ cout << "solution\n==================\n"; dump_solution(); } } continue; // All filled. } permute_square(level + 1, ret.x, ret.y); } if(!level) ; //this.worker.postMessage({ cmd : "update", value : a }); m_board[x][y] = 0; //this.report(); } uint64_t count_blanks() { uint64_t count = 0; for(uintN x = 0; x < 9; ++x) for(uintN y = 0; y < 9; ++y) if(!m_board[x][y]) ++count; return count; } uint64_t count() { solution_count = 0; cout << "Initial puzzle\n==================\n"; dump_solution(); if(!all) { if(count_blanks() > 63) { cerr << "too many blanks" << endl; return 0; } } if(!valid()) return 0; BlankFinderResult ret = first_blank(0,0); if(!ret.good) return 1; // Already done. permute_square(0, ret.x, ret.y); //document.gSudokuBoard.m_pieces = backup; //this.report(); return solution_count; } void dump_solution() { for(uintN y = 0; y < 9; ++y) { //cout << '[' (9-y) << ']'; for(uintN x = 0; x < 9; ++x) { uintN v = m_board[x][9-y-1].number(); if(v) cout << ' ' << v; else cout << " "; } cout << '\n'; } } bool row_valid(uintN y) { BlankFinderResult found[9]; uintN x; for(x = 0; x < 9; ++x) { if(!m_board[x][y]) continue; BlankFinderResult & loc = found[m_board[x][y]-1]; //cout << "Saw " << m_board[x][y] << " in " // "(" << (x+1) << ", " << (y+1) << ")." << endl; if(loc.good) { cerr << "row_valid: number " << m_board[x][y] << " found in (" << (loc.x+1) << ", " << (loc.y+1) << ") AND in (" << (x+1) << ", " << (y+1) << ")." << endl; return false; } loc = BlankFinderResult(x, y, true); //cout << "Noting " << m_board[x][y] << " in " // "(" << (x+1) << ", " << (y+1) << ")." << endl; } return true; } bool column_valid(uintN x) { BlankFinderResult found[9]; uintN y; for(y = 0; y < 9; ++y) { if(!m_board[x][y]) continue; BlankFinderResult & loc = found[m_board[x][y]-1]; if(loc.good) { cerr << "column_valid: number " << m_board[x][y] << " found in (" << (loc.x+1) << ", " << (loc.y+1) << ") AND in (" << (x+1) << ", " << (y+1) << ")." << endl; return false; } loc = BlankFinderResult(x, y, true); } return true; } bool grid_valid(uintN x0, uintN y0) { BlankFinderResult found[9]; uintN x, y; for(x = x0; x < (x0+3); ++x) { for(y = y0; y < (y0+3); ++y) { if(!m_board[x][y]) continue; BlankFinderResult & loc = found[m_board[x][y]-1]; if(loc.good) { cerr << "grid_valid: number " << m_board[x][y] << " found in (" << (loc.x+1) << ", " << (loc.y+1) << ") AND in (" << (x+1) << ", " << (y+1) << ")." << endl; return false; } loc = BlankFinderResult(x, y, true); } } return true; } bool valid() { for(uintN y = 0; y < 9; ++y) if(!row_valid(y)) return false; for(uintN x = 0; x < 9; ++x) if(!column_valid(x)) return false; for(uintN x = 0; x < 3; ++x) for(uintN y = 0; y < 3; ++y) if(!grid_valid(x*3,y*3)) return false; return true; } }; } // namespace Sudoku { JSBool board(JSContext *cx, JSObject *pObj, uintN argc, jsval *argv, jsval *vp) { cout << "board" << endl; (void)pObj; if ((!argc) || (!JSVAL_IS_OBJECT(argv[0]))) { cerr << "Failed to get board data." << endl; return JS_FALSE; } JSObject * obj = JSVAL_TO_OBJECT(argv[0]); if(!obj) { cerr << "Board data isn't an object." << endl; return JS_FALSE; } uintN n, rc; Sudoku::Solver * psolver; if(g_all) { if(g_quiet) psolver = new Sudoku::SolverT< true, true >; else psolver = new Sudoku::SolverT< true, false >; }else{ if(g_quiet) psolver = new Sudoku::SolverT< false, true >; else psolver = new Sudoku::SolverT< false, false >; } Sudoku::Solver & solver = * psolver; for(n = 0; n < 9; ++n) { char name[3]; cout << '[' << (n+1) << ']'; sprintf(name, "%u", n); jsval numarr; JSBool b = JS_GetProperty(cx, obj, name, & numarr); if(!b) { cerr << "\nFailed to get board data for number " << (n + 1) << '.' << endl; return JS_FALSE; } if(!JSVAL_IS_OBJECT(numarr)) return JS_FALSE; JSObject * numobj = JSVAL_TO_OBJECT(numarr); if(!numobj) { cerr << "\nNumber [" << (n+1) << "] object isn't an object." << endl; return JS_FALSE; } for(rc = 0; rc < 81; ++rc) { // At most 81 squares. char name[3]; sprintf(name, "%u", rc); jsval numval; // Any not-present property has a value of undefined. JSBool b = JS_GetProperty(cx, numobj, name, & numval); if(!b) { cerr << "\nFailed to get board data[" << rc << "] for number " << (n + 1) << '.' << endl; return JS_FALSE; } // Try all those that work. uint32_t val, x, y; // undefined -> uint32_t(0). if(!JS_ConvertArguments(cx, 1, & numval, "u", &val) || !val) break; x = (val / 10) - 1; y = (val % 10) - 1; cout << " " << (x+1) << (y+1); solver.m_board[x][y] = n + 1; } cout << '\n'; } solver.count(); solutions[puzzle] = solution_count; delete psolver; JS_SET_RVAL(cx, vp, JSVAL_VOID); /* return undefined */ return JS_TRUE; } JSBool text(JSContext *cx, JSObject *pObj, uintN argc, jsval *argv, jsval *vp) { (void)pObj; (void)argv; const char *cmd; if (!JS_ConvertArguments(cx, argc, argv, "s", &cmd)) return JS_FALSE; last_text = cmd; //cout << "text(" << last_text << ')' << endl; JS_SET_RVAL(cx, vp, JSVAL_VOID); /* return undefined */ return JS_TRUE; } JSBool noop(JSContext *cx, JSObject *pObj, uintN argc, jsval *argv, jsval *vp) { (void)pObj; (void)argc; (void)argv; JS_SET_RVAL(cx, vp, JSVAL_VOID); /* return undefined */ //cout << "noop" << endl; return JS_TRUE; } static JSFunctionSpec myjs_global_functions[] = { JS_FS("clear", noop, 1, 0, 0), JS_FS("text", text, 1, 0, 0), JS_FS("board", board, 1, 0, 0), JS_FS("delay", noop, 1, 0, 0), JS_FS("number", noop, 1, 0, 0), JS_FS("numbers", noop, 1, 0, 0), JS_FS("l2r", noop, 1, 0, 0), JS_FS("r2l", noop, 1, 0, 0), JS_FS("b2t", noop, 1, 0, 0), JS_FS("t2b", noop, 1, 0, 0), JS_FS("slide", noop, 1, 0, 0), JS_FS("sliders", noop, 1, 0, 0), JS_FS("slideX", noop, 1, 0, 0), JS_FS("slidersX", noop, 1, 0, 0), JS_FS("textX", noop, 1, 0, 0), JS_FS("numberX", noop, 1, 0, 0), JS_FS("numbersX", noop, 1, 0, 0), JS_FS("l2rX", noop, 1, 0, 0), JS_FS("r2lX", noop, 1, 0, 0), JS_FS("b2tX", noop, 1, 0, 0), JS_FS("t2bX", noop, 1, 0, 0), JS_FS_END }; /* The class of the global object. */ static JSClass global_class = { "global" , JSCLASS_GLOBAL_FLAGS , JS_PropertyStub , JS_PropertyStub , JS_PropertyStub , JS_PropertyStub // JS_StrictPropertyStub , JS_EnumerateStub , JS_ResolveStub , JS_ConvertStub , JS_FinalizeStub , JSCLASS_NO_OPTIONAL_MEMBERS }; /* The error reporter callback. */ void reportError(JSContext *cx, const char *message, JSErrorReport *report) { fprintf(stderr, "%s:%u:%s\n", report->filename ? report->filename : "<no filename>", (unsigned int) report->lineno, message); } /* JS variables. */ JSRuntime *rt; JSContext *cx; JSObject *global; string dir; string puzzle_fn_name(const char * file) { const char * last_slash = strrchr(file, '/'); if(!last_slash) return "no_slash"; const char * last_dot = strrchr(last_slash, '.'); if(!last_dot) return "no_dot"; return string(last_slash + 1, last_dot); } int process_script(const char * file) { // Call function puzzlefn_eh20081122md() puzzle = puzzle_fn_name(file); if(g_all) { if(puzzle != "empty") return 0; }else{ if(puzzle == "empty") return 0; } int fd = open(file, O_RDONLY); if(!fd) return 1; size_t length = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); char * src = (char *)mmap(0, length, PROT_READ, MAP_SHARED, fd, 0); if(src == ((char *)-1)) { cerr << "Couldn't mmap(" << file << ")." << endl; return 1; } JSBool b = JS_EvaluateScript(/*JSContext * */cx, /*JSObject *obj*/global, src, /*uintN */length, file, /*uintN lineno*/1, /*jsval *rval*/0); if(!b) { cerr << "Executing script(" << file << ") failed." << endl; munmap(src, length); return 1; } munmap(src, length); string call = string("puzzlefn_") + puzzle + "()"; cout << "Calling " << call << " for file(" << file << ")." << endl; b = JS_EvaluateScript(/*JSContext * */cx, /*JSObject *obj*/global , call.c_str(), /*uintN */call.length(), "<call>" , /*uintN lineno*/1, /*jsval *rval*/0); if(!b) { cerr << "Executing call for file(" << file << ") failed." << endl; return 1; } return 0; } set< string > to_process; int process_dir_entry(const char * file, const struct stat * p, int type) { if(type != FTW_F) return 0; if(file[strlen(file)-1] == '~') return 0; // Skip backups. puzzle = puzzle_fn_name(file); if(g_all) { if(puzzle != "empty") return 0; }else{ if(puzzle == "empty") return 0; } to_process.insert(file); return 0; } int process_dir() { int ret = ftw(dir.c_str(), & process_dir_entry, 100); if(ret) return ret; cout << to_process.size() << " files to process." << endl; set< string >::const_iterator i = to_process.begin(); set< string >::const_iterator j = to_process.end(); for(; i != j; ++i) { const string & file = *i; cout << "Processing " << file << '{' << endl; ret = process_script(file.c_str()); cout << "Processing " << file << "} " << ret << endl; if(ret) return ret; } return 0; } int Usage() { cerr << "Usage: sudoku-solver [-a] [-q] <dir>" << endl; return 1; } int mainX(int argc, const char *argv[]) { for(int narg = 1; narg < argc; ++narg) { const char * arg = argv[narg]; if(strlen(arg) < 1) return Usage(); if(arg[0] == '-') { if(strlen(arg) < 2) return Usage(); if(arg[1] == 'a') g_all = true; else if(arg[1] == 'q') g_quiet = true; else return Usage(); }else{ if(dir.length()) return Usage(); dir = arg; } } /* Create a JS runtime. */ rt = JS_NewRuntime(8L * 1024L * 1024L); if (rt == NULL) return 1; /* Create a context. */ cx = JS_NewContext(rt, 8192); if (cx == NULL) return 1; JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT /*| JSOPTION_METHODJIT*/); JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, reportError); /* Create the global object in a new compartment. */ //global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL); //global = JS_NewGlobalObject(cx, &global_class, NULL); global = JS_NewObject(cx, &global_class, NULL, NULL); if (global == NULL) return 1; /* Populate the global object with the standard globals, like Object and Array. */ if (!JS_InitStandardClasses(cx, global)) return 1; /* Your application code here. This may include JSAPI calls to create your own custom JS objects and run scripts. */ if (!JS_DefineFunctions(cx, global, myjs_global_functions)) return 1; // Read in the scripts, one at a time, and print their solutions. int ret = 0; if(process_dir()) ret = 1; /* Cleanup. */ JS_DestroyContext(cx); JS_DestroyRuntime(rt); JS_ShutDown(); cout << "Summary." << endl; cout << "Name Count" << endl; cout << "==================== =====" << endl; SolutionsMap::const_iterator i = solutions.begin(); SolutionsMap::const_iterator j = solutions.end(); for(; i != j; ++i) cout << left << setw(20) << i->first << ' ' << right << setw(5) << i->second << endl; return ret; } int main(int argc, const char *argv[]) { (void)argc; (void)argv; Sudoku::Row row; cout << "Values"; for(int n = 0; n < 9; ++n) cout << ' ' << uintN(row[n]); cout << endl; return 0; }

