Branch: Tag:

2018-11-30

2018-11-30 17:45:37 by William Welliver <william@welliver.org>

debugger: allow creation of breakpoints on programs that haven't been created yet.

warning: this code almost certainly has a number of crashers. it works in the most
basic of situations but don't expect much more from it yet.

31:   #define PIKE_WARNINGS 1   #endif /* PIKE_WARNINGS */    + int want_load_announcements = 0; + #define PROGRAM_LOADED(A,B,C) (want_load_announcements?(A[B]=program_loaded(B, (C))):(A[B]=(C)))      // --- Global constants and variables   
1706:    if (decoded?->this_program_does_not_exist) {    resolv_debug ("low_findprog %s: program claims not to exist\n",    fname); -  return programs[fname] = 0; +  return PROGRAM_LOADED(programs, fname, 0);    }    else {    if (objectp(decoded)) {
1717:    ret = decoded;    }    resolv_debug("low_findprog %s: returning %O\n", fname, ret); -  return programs[fname]=ret; +  return PROGRAM_LOADED(programs, fname, ret);    }    };    DEC_RESOLV_MSG_DEPTH();    resolv_debug ("low_findprog %s: dump decode failed\n", fname); -  programs[fname] = no_value; +  PROGRAM_LOADED(programs, fname, no_value);    call_compile_warning (handler, oname,    "Decode failed: " +    call_describe_error(err));
1736:       resolv_debug ("low_findprog %s: compiling, mkobj: %O\n", fname, mkobj);    INC_RESOLV_MSG_DEPTH(); -  programs[fname]=ret=__empty_program(0, fname); +  PROGRAM_LOADED(programs, fname, ret=__empty_program(0, fname));    AUTORELOAD_CHECK_FILE (fname);    string src;    if (array|object err = catch (src = master_read_file (fname))) {    DEC_RESOLV_MSG_DEPTH();    resolv_debug ("low_findprog %s: failed to read file\n", fname);    objects[ret] = no_value; -  ret=programs[fname]=0; // Negative cache. +  PROGRAM_LOADED(programs, fname, ret=0); // Negative cache.    compile_cb_rethrow (err);    }    if ( mixed e=catch {
1755:    DEC_RESOLV_MSG_DEPTH();    resolv_debug ("low_findprog %s: compilation failed\n", fname);    objects[ret] = no_value; -  ret=programs[fname]=0; // Negative cache. +  PROGRAM_LOADED(programs, fname, ret=0); // Negative cache.    destruct(compiler_lock);    throw(e);    }
1775:    DEC_RESOLV_MSG_DEPTH();    resolv_debug ("low_findprog %s: failed to load binary\n", fname);    objects[ret] = no_value; -  ret=programs[fname]=0; // Negative cache. +  PROGRAM_LOADED(programs, fname, ret=0); // Negative cache.    if (objectp (err) && err->is_module_load_error)    // Do not treat errors from dlopen(3) as exceptions since in    // a dist we can have .so files that are dynamically linked
1800:       if (ret?->this_program_does_not_exist) {    resolv_debug ("low_findprog %s: program says it doesn't exist\n", fname); -  return programs[fname] = 0; +  PROGRAM_LOADED(programs, fname, ret=0); +  return ret;    }    else {    if(!ret)    resolv_debug("low_findprog %s: dependencies failed.\n", fname);    else    resolv_debug("low_findprog %s: returning %O\n", fname, ret); -  return programs[fname]=ret; +  PROGRAM_LOADED(programs, fname, ret); +  return ret;    }    }   
1830:    if (m_delete (rev_programs, p))    m_delete (programs, fname);    else -  programs[fname] = no_value; +  PROGRAM_LOADED(programs, fname, no_value);       string name = program_path_to_name (fname);    mixed n = has_value (name, '.') ?
3637:    return v;   };    + // TODO: this seems like a backward approach. The debugger should register its completer on startup. + // callback for completing breakpoint registration for programs which weren't loaded + // at the time of the breakpoint's creation. + function deferred_breakpoint_completer; + mixed program_loaded(string fn, mixed c) {if(deferred_breakpoint_completer) deferred_breakpoint_completer(fn, c); return c;} +    void load_debugger(int wait_seconds) { -  +  want_load_announcements = 1;    set_debugger(1);    // load the debugger support    function d;
3652:    }       err = catch { +  deferred_breakpoint_completer = main_resolv("Debug.Debugger.deferred_breakpoint_completer", +  get_compilation_handler(compat_major, compat_minor)); +  }; +  +  if(err) { +  werror("Unable to load the deferred breakpoint completer\n"); +  werror(describe_backtrace(err)); +  exit(1); +  } +  +  err = catch {    d = main_resolv("Debug.Debugger.debug_server",    get_compilation_handler(compat_major, compat_minor));    };
4099:    // Don't list the program with its real path in the programs    // mapping, so that reverse lookups (typically by the codec)    // always find the canonical "/main" instead. -  programs[argv[0]] = no_value; +  PROGRAM_LOADED(programs, argv[0], no_value);    }    -  programs["/main"] = prog; +  PROGRAM_LOADED(programs, "/main", prog);       // FIXME: Can this occur at all?    if(!prog)
5734:    {    unregistered = 0;    resolv_debug("register %s\n", fname); -  programs[fname]=p; +  PROGRAM_LOADED(programs, fname, p);    if (mkobj)    DEC_RETURN (objectp (objects[p]) ? objects[p] : (objects[p]=__null_program()));    }