Using DBMS_DEBUG

To debug server-side code, it is necessary to have two database sessions: one session to run the code in debug-mode (the target session), and a second session to supervise the target session (the debug session).

The target session becomes available for debugging by making initializing calls with DBMS_DEBUG. This marks the session, so the PL/SQL interpreter runs in debug-mode and generates debug events. As debug events are generated, they are posted from the session. In most cases, debug events require return notification: the interpreter pauses awaiting a reply.

Meanwhile, the debug session must also initialize itself using DBMS_DEBUG: This tells it what target session to supervise. The debug session may then call entrypoints in DBMS_DEBUG to read events that were posted from the target session and to communicate with the target session.

See Also:

Figure 9-1 and Figure 9-2 illustrate the flow of operations in the session to be debugged and in the debugging session.

DBMS_DEBUG does not provide any interface to the PL/SQL compiler; however, it does depend on debug information optionally generated by the compiler. Without debug information, it is not possible to examine or modify the values of parameters or variables. There are two ways to ensure that debug information is generated: through a session switch, or through individual recompilation.

To set the session switch, enter the following statement:

ALTER SESSION SET PLSQL_DEBUG = true;

This instructs the compiler to generate debug information for the remainder of the session. It does not recompile any existing PL/SQL.

To generate debug information for existing PL/SQL code, use one of the following statements (the second recompiles a package or type body):

Figure 9-2 Debug Session (Cont.)

Control of the Interpreter

At startup of the interpreter so any deferred breakpoints may be installed prior to execution.

At any line containing an enabled breakpoint.

At any line where an interesting event occurs. The set of interesting events is specified by the flags passed to DBMS_DEBUG.CONTINUE in the breakflags parameter.

Usage Notes

Session Termination

There is no event for session termination. Therefore, it is the responsibility of the debug session to check and make sure that the target session has not ended. A call to DBMS_DEBUG.SYNCHRONIZE after the target session has ended causes the debug session to hang until it times out.

Deferred Operations

The diagram suggests that it is possible to set breakpoints prior to having a target session. This is true. In this case, Probe caches the breakpoint request and transmits it to the target session at first synchronization. However, if a breakpoint request is deferred in this fashion, then:

SET_BREAKPOINT does not set the breakpoint number (it can be obtained later from SHOW_BREAKPOINTS if necessary).

SET_BREAKPOINT does not validate the breakpoint request. If the requested source line does not exist, then an error silently occurs at synchronization, and no breakpoint is set.

Diagnostic Output

To debug Probe, there are diagnostics parameters to some of the calls in DBMS_DEBUG. These parameters specify whether to place diagnostic output in the RDBMS tracefile. If output to the RDBMS tracefile is disabled, then these parameters have no effect.

Types and Constants

Types

PROGRAM_INFO

This type specifies a program location. It is a line number in a program unit. This is used for stack backtraces and for setting and examining breakpoints. The read-only fields are currently ignored by Probe for breakpoint operations. They are set by Probe only for stack backtraces.

EntrypointName

Null, unless this is a nested procedure or function.

LibunitType

Disambiguate among objects that share the same namespace (for example, procedure and package specifications).

TYPE program_info IS RECORD
(
-- The following fields are used when setting a breakpoint
Namespace BINARY_INTEGER, -- See 'NAMESPACES' section below.
Name VARCHAR2(30), -- name of the program unit
Owner VARCHAR2(30), -- owner of the program unit
Dblink VARCHAR2(30), -- database link, if remote
Line# BINARY_INTEGER,
-- Read-only fields (set by Probe when doing a stack backtrace)
LibunitType BINARY_INTEGER,
EntrypointName VARCHAR2(30)
);

INDEX_TABLE

This type is used by GET_INDEXES to return the available indexes for an indexed table.

TYPE index_table IS table of BINARY_INTEGER INDEX BY BINARY_INTEGER;

BACKTRACE_TABLE

This type is used by PRINT_BACKTRACE.

TYPE backtrace_table IS TABLE OF program_info INDEX BY BINARY_INTEGER;

BREAKPOINT_TABLE

This type is used by SHOW_BREAKPOINTS.

TYPE breakpoint_table IS TABLE OF breakpoint_info INDEX BY BINARY_INTEGER;

VC2_TABLE

This type is used by SHOW_SOURCE.

TYPE vc2_table IS TABLE OF VARCHAR2(90) INDEX BY BINARY_INTEGER;

Constants

A breakpoint status may have these values:

breakpoint_status_unused

Breakpoint is not in use.

Otherwise, the status is a mask of the following values:

breakpoint_status_active

A line breakpoint.

breakpoints_status_disabled

Breakpoint is currently disabled.

breakpoint_status_remote

A 'shadow' breakpoint (a local representation of a remote breakpoint).

NAMESPACES

Program units on the server reside in different namespaces. When setting a breakpoint, specify the desired namespace.

Namespace_cursor contains cursors (anonymous blocks).

Namespace_pgkspec_or_toplevel contains:

Package specifications.

Procedures and functions that are not nested inside other packages, procedures, or functions.

Object types.

Namespace_pkg_body contains package bodies and type bodies.

Namespace_trigger contains triggers.

Libunit Types

These values are used to disambiguate among objects in a given namespace. These constants are used in PROGRAM_INFO when Probe is giving a stack backtrace.

LibunitType_cursor

LibunitType_procedure

LibunitType_function

LibunitType_package

LibunitType_package_body

LibunitType_trigger

LibunitType_Unknown

Breakflags

These are values to use for the breakflags parameter to CONTINUE, in order to tell Probe what events are of interest to the client. These flags may be combined.

break_next_line

Break at next source line (step over calls).

break_any_call

Break at next source line (step into calls).

break_any_return

Break after returning from current entrypoint (skip over any entrypoints called from the current routine).

break_return

Break the next time an entrypoint gets ready to return. (This includes entrypoints called from the current one. If interpreter is running Proc1, which calls Proc2, then break_return stops at the end of Proc2.)

break_exception

Break when an exception is raised.

break_handler

Break when an exception handler is executed.

abort_execution

Stop execution and force an 'exit' event as soon as DBMS_DEBUG.CONTINUE is called.

Information Flags

These are flags which may be passed as the info_requested parameter to SYNCHRONIZE, CONTINUE, and GET_RUNTIME_INFO.

info_getStackDepth

Get the current depth of the stack.

info_getBreakpoint

Get the breakpoint number.

info_getLineinfo

Get program unit information.

Reasons for Suspension

After CONTINUE is run, the program either runs to completion or breaks on some line.

reason_none

reason_interpreter_starting

Interpreter is starting.

reason_breakpoint

Hit a breakpoint.

reason_enter

Procedure entry.

reason_return

Procedure is about to return.

reason_finish

Procedure is finished.

reason_line

Reached a new line.

reason_interrupt

An interrupt occurred.

reason_exception

An exception was raised.

reason_exit

Interpreter is exiting (old form).

reason_knl_exit

Kernel is exiting.

reason_handler

Start exception-handler.

reason_timeout

A timeout occurred.

reason_instantiate

Instantiation block.

reason_abort

Interpreter is aborting.

Error Codes, Exceptions, and Variables

Error Codes

These values are returned by the various functions called in the debug session (SYNCHRONIZE, CONTINUE, SET_BREAKPOINT, and so on). If PL/SQL exceptions worked across client/server and server/server boundaries, then these would all be exceptions rather than error codes.

success

Normal termination.

Statuses returned by GET_VALUE and SET_VALUE:

error_bogus_frame

No such entrypoint on the stack.

error_no_debug_info

Program was compiled without debug symbols.

error_no_such_object

No such variable or parameter.

error_unknown_type

Debug information is unreadable.

error_indexed_table

Returned by GET_VALUE if the object is a table, but no index was provided.

error_illegal_index

No such element exists in the collection.

error_nullcollection

Table is atomically null.

error_nullvalue

Value is null.

Statuses returned by SET_VALUE:

error_illegal_value

Constraint violation.

error_illegal_null

Constraint violation.

error_value_malformed

Unable to decipher the given value.

error_other

Some other error.

error_name_incomplete

Name did not resolve to a scalar.

Statuses returned by the breakpoint functions:

error_no_such_breakpt

No such breakpoint.

error_idle_breakpt

Cannot enable or disable an unused breakpoint.

error_bad_handle

Unable to set breakpoint in given program (non-existent or security violation).

General error codes (returned by many of the DBMS_DEBUG subprograms):

error_unimplemented

Functionality is not yet implemented.

error_deferred

No program running; operation deferred.

error_exception

An exception was raised in the DBMS_DEBUG or Probe packages on the server.

error_communication

Some error other than a timeout occurred.

error_timeout

Timout occurred.

Exceptions

illegal_init

DEBUG_ON was called prior to INITIALIZE.

The following exceptions are raised by procedure SELF_CHECK:

pipe_creation_failure

Could not create a pipe.

pipe_send_failure

Could not write data to the pipe.

pipe_receive_failure

Could not read data from the pipe.

pipe_datatype_mismatch

Datatype in the pipe was wrong.

pipe_data_error

Data got garbled in the pipe.

Variables

default_timeout

The timeout value (used by both sessions).The smallest possible timeout is 1 second. If this value is set to 0, then a large value (3600) is used.

Common and Debug Session Sections

Common Section

The following subprograms may be called in either the target or the debug session:

OER Breakpoints

Exceptions that are declared in PL/SQL programs are known as user-defined exceptions. In addition, there are Oracle Errors (OERs) that are returned from the Oracle kernel. To tie the two mechanisms together, PL/SQL provides the "exception_init" pragma that turns a user-defined exception into an OER, so that a PL/SQL handler may be used for it, and so that the PL/SQL engine can return OERs to the Oracle kernel. As of the current release, the only information available about an OER is its number. If two user-defined exceptions are exception_init'd to the same OER, they are indistinguishable.