Managing Debugpoints

Debugging can be enabled in a session by calling the procedure dbms_mle.enable_debugging with a debug specification.

In addition to an array of debugpoints, specified via the debugpoints field, a debug specification includes a version identifier, specified via the version field. The version field must be set to the value "1.0". Debug specifications can include debugpoints for multiple MLE modules.

Note:

Debug specifications require module names to be provided in the same case that they are stored in the dictionary. By default, module names are stored in uppercase unless the name is enclosed in double-quotation marks during module creation.

The procedure dbms_mle.enable_debugging also accepts a BLOB sink to which the debug output is written.

After the call to dbms_mle.enable_debugging, all debugpoints included in the debug specification are active. Every time one of the debugpoints is hit, the associated debug information is logged. The debug information is written out to the BLOB sink when control passes from MLE back to PL/SQL at the latest but could be written out in part or in full before this point:
  • For dynamic MLE evaluations, control passes from MLE to PL/SQL when the call to dbms_mle.eval returns.

  • For MLE call specifications, control passes from MLE to PL/SQL when the call to the MLE call specification returns.

The installed debugpoints are active for all executions of the MLE modules regardless of which user's privileges the MLE code executes with.

Calling dbms_mle.enable_debugging again in the same session replaces the existing set of debugpoints. Debugpoints remain active until either the session ends or the user disables debugging explicitly by calling dbms_mle.disable_debugging.

Example 9-5 Enabling Debugging of an MLE Module

The debug specification in this example references the module count_module, created at the beginning of Example 6-4, and module in_out_example_mod, created in Example 6-6.

DECLARE
  debugspec json;
  sink blob;
BEGIN
  debugspec:= json('
    {
      "version": "1.0",
      "debugpoints": [
        {
          "at": {
            "name": "COUNT_MODULE",
            "line": 7 
          },
          "actions": [
            { "type": "watch", "id": "myCounter", "depth": 1 }
            ],
          "condition": "myCounter > 0"
        },
        {
          "at": {
            "name": "IN_OUT_EXAMPLE_MOD",
            "line": 16
          },
          "actions": [
            { "type": "snapshot" }
          ],
        }
      ]
    }
  ');
  dbms_lob.createtemporary(sink, false);
  dbms_mle.enable_debugging(debugspec, sink);
  --run application to debug
END;
/

Debugging Security Considerations

Users must either own the MLE modules being debugged or have debugging privileges to it. This is necessary because the debugging feature allows you to observe runtime state of the MLE code.

Additionally, because the condition field allows you to execute arbitrary code, this could potentially be used to alter the runtime behavior of the code being debugged. Concretely, you can use post-execution debugging on an MLE module if,
  • You own the MLE module, or

  • You have the COLLECT DEBUG INFO object privilege on the MLE module.

Privileges are checked every time code in an MLE module with one or more active debugpoints is executed. If you attempt to install debugpoints without the necessary privileges, an ORA-04164 error will be raised.

If an ORA-04164 is encountered, either
  • The user who installed the debugpoints must be granted the COLLECT DEBUG INFO privilege on the module in question, or

  • The debugpoints for the module must be disabled to continue executing code in the module in that session.

COLLECT DEBUG INFO Privilege for MLE Modules

The COLLECT DEBUG INFO object privilege for MLE modules controls whether a user who does not own a module, but has EXECUTE privilege, can still perform debugging on said module.

For instance, consider an MLE module, ModuleA, owned by user W. User W creates an invoker's rights call specification for a function in ModuleA and grants EXECUTE on this call specification on user V. For user V to have the ability to debug the code in ModuleA when calling this call specification, user W must also grant them the COLLECT DEBUG INFO privilege on ModuleA.

User W could use the following statement to grant user V the privilege to debug ModuleA:

GRANT COLLECT DEBUG INFO ON ModuleA TO V;

The COLLECT DEBUG INFO privilege can subsequently be revoked if needed:

REVOKE COLLECT DEBUG INFO ON ModuleA FROM V;