home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / +Sandman / Softice_Tuts.ZIP / Homepage / si-ug-chapter13.txt
Encoding:
Text File  |  1998-06-27  |  27.9 KB  |  688 lines

  1.                                            You know my methods. Apply them.
  2.                                                      Sir Arthur Conan Doyle
  3.  
  4. Using Breakpoints
  5.  
  6.      Introduction
  7.      Types of Breakpoints Supported by SoftICE
  8.           Breakpoint Options
  9.           Execution Breakpoints
  10.           Memory Breakpoints
  11.           Interrupt Breakpoints
  12.           I/O Breakpoints
  13.           Window Message Breakpoints
  14.      Understanding Breakpoint Contexts
  15.      Virtual Breakpoints
  16.      Setting a Breakpoint Action
  17.      Conditional Breakpoints
  18.           Conditional Breakpoint Count Functions
  19.           Using Local Variables in Conditional Expressions
  20.           Referencing the Stack in Conditional Breakpoints
  21.           Performance
  22.           Duplicate Breakpoints
  23.      Elapsed Time
  24.      Breakpoint Statistics
  25.      Referring to Breakpoints in Expressions
  26.      Manipulating Breakpoints
  27.      Using Embedded Breakpoints
  28.  
  29. Introduction
  30.  
  31.      You can use SoftICE to set breakpoints on program execution, memory
  32.      location reads and writes, interrupts, and reads and writes to I/O
  33.      ports. SoftICE assigns a breakpoint index, from 0 to FF, to each
  34.      breakpoint. You can use this breakpoint index to identify breakpoints
  35.      when you set, delete, disable, enable, or edit them.
  36.  
  37.      All SoftICE breakpoints are sticky, which means that SoftICE tracks
  38.      and maintains a breakpoint until you intentionally clear or disable it
  39.      using the BC or the BD command. After you clear breakpoints, you can
  40.      recall them with the BH command, which displays a breakpoint history.
  41.  
  42.      You can set up to 256 breakpoints at one time in SoftICE. However, the
  43.      number of breakpoints you can set on memory location (BPMs) and I/O
  44.      ports (BPIOs) is a total of four, due to restrictions of the x86
  45.      processors.
  46.  
  47.      Where symbol information is available, you can set breakpoints using
  48.      function names. When in source or mixed mode, you can set
  49.      point-and-shoot style breakpoints on any source code line. A valuable
  50.      feature is that you can set point-and-shoot breakpoints in a module
  51.      before it is even loaded.
  52.  
  53. Types of Breakpoints Supported by SoftICE
  54.  
  55.      SoftICE provides a powerful array of breakpoint capabilities that take
  56.      full advantage of the x86 architecture, as follows :
  57.  
  58.    * Execution Breakpoints: SoftICE replaces an existing instruction with
  59.      INT 3. You can use the BPX command to set execution breakpoints.
  60.  
  61.    * Memory Breakpoints: SoftICE uses the x86 debug registers to break when
  62.      a certain byte/word/dword of memory is read, written, or executed. You
  63.      can use the BPM command to set memory breakpoints.
  64.  
  65.    * Interrupt Breakpoints: SoftICE intercepts interrupts by modifying the
  66.      IDT (Interrupt Descriptor Table) vectors. You can use the BPINT
  67.      command to set interrupt breakpoints.
  68.  
  69.    * I/O Breakpoints: SoftICE uses a debug register extension available on
  70.      Pentium and Pentium-Pro CPUs to watch for an IN or OUT instruction
  71.      going to a particular port address. You can use the BPIO command to
  72.      set I/O breakpoints.
  73.  
  74.    * Window Message Breakpoints: SoftICE traps when a particular message or
  75.      range of messages arrives at a window. This is not a fundamental
  76.      breakpoint type; it is just a convenient feature built on top of the
  77.      other breakpoint primitives. You can use the BMSG command to set
  78.      window message breakpoints.
  79.  
  80. Breakpoint Options
  81.  
  82.      You can qualify each type of breakpoint with the following two
  83.      options:
  84.  
  85.    * A conditional expression [IF expression]: The expression must evaluate
  86.      to non-zero (TRUE) for the breakpoint to trigger. Refer to Conditional
  87.      Breakpoints.
  88.  
  89.    * A breakpoint action [DO "command1;command2;"]: A series of SoftICE
  90.      commands can automatically execute when the breakpoint triggers. You
  91.      can use this feature in concert with user-defined macros to automate
  92.      tasks that would otherwise be tedious. Refer to Setting a Breakpoint
  93.      Action on page 114.
  94.  
  95.      Note: For complete information on each breakpoint command, refer to
  96.      the SoftICE Command Reference.
  97.  
  98. Execution Breakpoints
  99.  
  100.      An execution breakpoint traps executing code such as a function call
  101.      or language statement. This is the most frequently used type of
  102.      breakpoint. By replacing an existing instruction with an INT 3
  103.      instruction, SoftICE takes control when execution reaches the INT 3
  104.      breakpoint.
  105.  
  106.      SoftICE provides two ways for setting execution breakpoints: using a
  107.      mouse and using the BPX command. The following sections describe how
  108.      to use these methods for setting breakpoints.
  109.  
  110. Using a Mouse to Set Breakpoints
  111.  
  112.      If you are using a Pentium processor and a mouse, you can use the
  113.      mouse to set or clear point-and-shoot (sticky) and one-shot
  114.      breakpoints. To set a sticky breakpoint, double-click the line on
  115.      which you want to set the breakpoint. SoftICE highlights the line to
  116.      indicate that you set a breakpoint. Double-click the line again to
  117.      clear the breakpoint. To set a one-shot breakpoint, click the line on
  118.      which you want to set the breakpoint and use the HERE command (F7) to
  119.      execute to that line.
  120.  
  121. Using the BPX Command to Set Breakpoints
  122.  
  123.      Use the BPX command with any of the following parameters to set an
  124.      execution breakpoint:
  125.  
  126.      BPX [address] [IF expression] [DO "command1;command2;"]
  127.  
  128.      IF expression:
  129.           Refer to Conditional Breakpoints.
  130.      DO "command1;command2;":
  131.           Refer to Setting a Breakpoint Action.
  132.  
  133.      Example:
  134.  
  135.           To set a breakpoint on your application's WinMain function, use
  136.           this command:
  137.  
  138.           BPX WinMain
  139.  
  140.      Use the BPX command without specifying any parameter to set a
  141.      point-and-shoot execution breakpoint in the source code. Use Alt-C to
  142.      move the cursor into the Code window. Then use the arrow keys to
  143.      position the cursor on the line on which you want to set the
  144.      breakpoint. Finally, use the BPX command (F9). If you prefer to use
  145.      your mouse to set the breakpoint, click the scroll arrows to scroll
  146.      the Code window, then double-click the line on which you want to set
  147.      the breakpoint.
  148.  
  149. Memory Breakpoints
  150.  
  151.      A memory breakpoint uses the debug registers found on the 386 CPUs and
  152.      later models to monitor access to a certain memory location. This type
  153.      of breakpoint is extremely useful for finding out when and where a
  154.      program variable is modified, and for setting an execution breakpoint
  155.      in read-only memory. You can only set four memory breakpoints at one
  156.      time, because the CPU contains only four debug registers.
  157.  
  158.      Use the BPM command to set memory breakpoints:
  159.  
  160.      BPM[B|W|D] address [R|W|RW|X] [ debug register] [IF expression]
  161.         [DO "command1;command2;"]
  162.  
  163.      BPM and BPMB:
  164.           Set a byte-size breakpoint.
  165.      BPMW:
  166.           Sets a word (2-byte) size breakpoint.
  167.      BPMD:
  168.           Sets a dword (4-byte) size breakpoint.
  169.      R, W, and RW:
  170.           Break on reads, writes, or both.
  171.      X:
  172.           Breaks on execution; this is more powerful than a BPX-style
  173.           breakpoint because memory does not need to be modified, enabling
  174.           such options as setting breakpoints in ROM or setting breakpoints
  175.           on addresses that are not present.
  176.      debug register:
  177.           Specifies which debug register to use. SoftICE normally manages
  178.           the debug register for you, unless you need to specify it in an
  179.           unusual situation.
  180.      IF expression:
  181.           Refer to Conditional Breakpoints.
  182.      DO "command1;command2;":
  183.           Refer to Setting a Breakpoint Action.
  184.  
  185.      Example:
  186.  
  187.           The following example sets a memory breakpoint to trigger when a
  188.           value of 5 is written to the Dword (4-byte) variable
  189.           MyGlobalVariable.
  190.  
  191.           BPMD MyGlobalVariable W IF MyGlobalVariable==5
  192.  
  193.      If the target location of a BPM breakpoint is frequently accessed,
  194.      performance can be degraded regardless of whether the conditional
  195.      expression evaluates to FALSE.
  196.  
  197. Interrupt Breakpoints
  198.  
  199.      Use an interrupt breakpoint to trap an interrupt through the IDT. The
  200.      breakpoint only triggers when a specified interrupt is dispatched
  201.      through the IDT.
  202.  
  203.      Use the BPINT command to set interrupt breakpoints:
  204.  
  205.      BPINT interrupt-number [IF expression] [DO "command1;command2;"]
  206.  
  207.      interrupt-number:
  208.           Number ranging from 0 to 255 (0 to FF hex).
  209.      IF expression:
  210.           Refer to Conditional Breakpoints.
  211.      DO "command1;command2;":
  212.           Refer to Setting a Breakpoint Action.
  213.  
  214.      If an interrupt is caused by a software INT instruction, the
  215.      instruction displayed will be the INT instruction. (SoftICE pops up
  216.      when execution reaches the INT instruction responsible for the
  217.      breakpoint, but before the instruction actually executes.) Otherwise,
  218.      the current instruction will be the first instruction of an interrupt
  219.      handler. You can list all interrupts and their handlers by using the
  220.      IDT command.
  221.  
  222.      Example:
  223.  
  224.           Use the following command to set a breakpoint to trigger when a
  225.           call to the kernel-mode routine NtCreateProcess is made from user
  226.           mode:
  227.  
  228.           BPINT 2E IF EAX==1E
  229.  
  230.           Note: The NtCreateProcess is normally called from ZwCreateProcess
  231.           in the NTDLL.DLL, which is in turn called from CreateProcessW in
  232.           the KERNEL32.DLL. In the conditional expression, 1E is the
  233.           service number for NtCreateProcess. Use the NTCALL command to
  234.           find this value.
  235.  
  236.      You can use the BPINT command to trap software interrupts, for
  237.      example, INT 21 made by 16-bit Windows programs. Note that software
  238.      interrupts issued from V86 mode do not pass through the IDT vector
  239.      that they specify. INT instructions executed in V86 generate processor
  240.      general protection faults (GPF), which are handled by vector 0xD in
  241.      the IDT. The Windows GPF handler realizes the cause of the fault and
  242.      passes control to a handler dedicated to specific V86 interrupt types.
  243.      The types may end up reflecting the interrupt down to V86 mode by
  244.      calling the interrupt handler entered in the V86 mode Interrupt Vector
  245.      Table (IVT). In some cases, a real-mode interrupt is reflected
  246.      (simulated) by calling the real-mode interrupt vector.
  247.  
  248.      In the case where the interrupt is reflected, you can trap it by
  249.      placing a BPX breakpoint at the beginning of the real-mode interrupt
  250.      handler.
  251.  
  252.      Example:
  253.  
  254.           To set a breakpoint on the real-mode INT 21 handler, use the
  255.           following command:
  256.  
  257.           BPX *($0:(21*4))
  258.  
  259. I/O Breakpoints
  260.  
  261.      An I/O breakpoint monitors reads and writes to a port address. The
  262.      breakpoint traps when an IN or OUT instruction accesses the port.
  263.      SoftICE implements I/O breakpoints by using the debug register
  264.      extensions introduced with the Pentium. As a result, I/O breakpoints
  265.      require a Pentium or Pentium-Pro CPU. A maximum of four I/O
  266.      breakpoints can be set at one time. The I/O breakpoint is effective in
  267.      kernel-level (ring 0) code as well as user (ring 3) code.
  268.  
  269.      Notes: Under Windows 95, SoftICE relies on the I/O permission bitmap,
  270.      which restricts I/O trapping to ring 3 code.
  271.  
  272.      Notes: You cannot use I/O breakpoints to trap IN/OUT instructions
  273.      executed by MS-DOS programs. The IN/OUT instructions are trapped and
  274.      emulated by the operating system, and therefore do not generate real
  275.      port I/O, at least not in a 1:1 mapping.
  276.  
  277.      Use the BPIO command to set I/O breakpoints:
  278.  
  279.      BPIO port-number [R|W|RW] [IF expression]
  280.         [DO "command1;command2;"]
  281.  
  282.      R, W, and RW :
  283.           Break on reads (IN instructions), writes (OUT instructions), or
  284.           both, respectively.
  285.      IF expression:
  286.           Refer to Conditional Breakpoints.
  287.      DO "command1;command2;":
  288.           Refer to Setting a Breakpoint Action.
  289.  
  290.      When an I/O breakpoint triggers and SoftICE pops up, the current
  291.      instruction is the instruction following the IN or OUT that caused the
  292.      breakpoint to trigger. Unlike BPM breakpoints, there is no size
  293.      specification; any access to the port-number, whether byte, word, or
  294.      dword, triggers the breakpoint. Any I/O that spans the I/O breakpoint
  295.      will also trigger the breakpoint. For example, if you set an I/O
  296.      breakpoint on port 2FF, a word I/O to port 2FE would trigger the
  297.      breakpoint.
  298.  
  299.      Example:
  300.  
  301.           Use the following command to set a breakpoint to trigger when a
  302.           value is read from port 3FEH with the upper 2 bits set:
  303.  
  304.           BPIO 3FE R IF (AL & C0)==C0
  305.  
  306.           The condition is evaluated after the instruction completes. The
  307.           value will be in AL, AX, or EAX because all port I/O, except for
  308.           the string I/O instructions (which are rarely used), use the EAX
  309.           register.
  310.  
  311. Window Message Breakpoints
  312.  
  313.      Use a window message breakpoint to trap a certain message or range of
  314.      messages delivered to a window procedure. Although you could implement
  315.      an equivalent breakpoint yourself using BPX with a conditional
  316.      expression, the following BMSG command is easier to use:
  317.  
  318.      BMSG window-handle [L] [ begin-message [ end-message]]
  319.         [IF expression] [DO "command1;command2;"]
  320.  
  321.      window-handle:
  322.           Value returned when the window was created; you can use the HWND
  323.           command to get a list of windows with their handles.
  324.      L:
  325.           Signifies that the window message should be printed to the
  326.           Command window without popping into SoftICE.
  327.      begin-message:
  328.           Single Windows message or the lower message number in a range of
  329.           Windows messages. If you do not specify a range with an
  330.           end-message, then only the begin-message will cause a break. For
  331.           both begin-message and end-message, the message numbers can be
  332.           specified either in hexadecimal or by using the actual ASCII
  333.           names of the messages, for example, WM_QUIT.
  334.      end-message:
  335.           Higher message number in a range of Windows messages.
  336.      IF expression:
  337.           Refer to Conditional Breakpoints.
  338.      DO "command1;command2;":
  339.           Refer to Setting a Breakpoint Action.
  340.  
  341.      When specifying a message or a message range, you can use the symbolic
  342.      name, for example, WM_NCPAINT. Use the WMSG command to get a list of
  343.      the window messages that SoftICE understands. If no message or message
  344.      range is specified, any message will trigger the breakpoint.
  345.  
  346.      Example:
  347.  
  348.           To set a window message breakpoint for the window handle 1001E,
  349.           use the following command:
  350.  
  351.           BMSG 1001E WM_NCPAINT
  352.  
  353.           SoftICE is smart enough to take into account the address context
  354.           of the process that owns the window, so it does not matter what
  355.           address context you are in when you use BMSG.
  356.  
  357.           You can construct an equivalent BPX-style breakpoint using a
  358.           conditional expression. Use the HWND command to get the address
  359.           of the window procedure, then use the following BPX command
  360.           (Win32 only):
  361.  
  362.           BPX 5FEBDD12 IF (esp->8)==WM_NCPAINT
  363.  
  364.      Warning: When setting a breakpoint using a raw address (not a symbol),
  365.      it is vital to be in the correct address context.
  366.  
  367. Understanding Breakpoint Contexts
  368.  
  369.      A breakpoint context consists of the address context in which the
  370.      breakpoint was set and in what code module the breakpoint is in, if
  371.      any. Breakpoint contexts apply to the BPX and BPM commands, and
  372.      breakpoint types based on those commands such as BMSG.
  373.  
  374.      For Win32 applications, breakpoints set in the upper 2GB of address
  375.      space are global; they break in any context. Breakpoints set in the
  376.      lower 2GB are context-sensitive; they trigger according to the
  377.      following criteria and SoftICE pops up:
  378.  
  379.         * SoftICE only pops up if the address context matches the context
  380.           in which the breakpoint was set.
  381.  
  382.         * If the breakpoint triggers in the same code module in which the
  383.           breakpoint was set, then SoftICE disregards the address context
  384.           and pops up. This means that a breakpoint set in a shared module
  385.           like KERNEL32.DLL breaks in every address context that has the
  386.           module loaded, regardless of what address context was selected
  387.           when the breakpoint was set.
  388.  
  389.           The exception is if another process mapped the module at a
  390.           different base address than the one in which the breakpoint is
  391.           set. In this case, the breakpoint does not trigger. Avoid this
  392.           situation by basing your DLLs at non-conflicting addresses.
  393.  
  394.      Breakpoints set on MS-DOS and 16-bit Windows programs are
  395.      context-sensitive too in the sense that the breakpoint only affects
  396.      the NTVDM process in which the breakpoint was set. The breakpoint
  397.      never crosses NTVDMs, even if the same program is run multiple times.
  398.  
  399.      Breakpoint contexts are more important for BPM-type breakpoints than
  400.      for BPX. BPM sets an x86 hardware breakpoint that triggers on a
  401.      certain virtual address. Because the CPU's breakpoint hardware knows
  402.      nothing of address spaces, it could potentially trigger on an
  403.      unrelated piece of code or data. Breakpoint contexts give SoftICE the
  404.      ability to discriminate between false traps and real ones.
  405.  
  406. Virtual Breakpoints
  407.  
  408.      In SoftICE, you can set breakpoints in Windows modules before they
  409.      load, and it is not necessary for a page to be present in physical
  410.      memory for a BPX (INT 3) breakpoint to be set. In such cases, the
  411.      breakpoint is virtual; it will be automatically armed when the module
  412.      loads or the page becomes present. Virtual breakpoints can only be set
  413.      on either symbols or source lines.
  414.  
  415. Setting a Breakpoint Action
  416.  
  417.      You can set a breakpoint to execute a series of SoftICE commands,
  418.      including user-defined macros, after the breakpoint is triggered. You
  419.      define these breakpoint actions with the DO option, which is available
  420.      with every breakpoint type:
  421.  
  422.      DO "command1;command2;"
  423.  
  424.      The body of a breakpoint action definition is a sequence of SoftICE
  425.      commands or other macros, separated by semicolons. You need not
  426.      terminate the final command with a semicolon.
  427.  
  428.      Breakpoint actions are closely related to macros. Refer to Working
  429.      with Persistent Macros on page 162 for more information about macros.
  430.      Breakpoint actions are essentially unnamed macros that do not accept
  431.      command-line arguments. Breakpoint actions, like macros, can call upon
  432.      macros. In fact a prime use of macros is to simplify the creation of
  433.      complex breakpoint actions.
  434.  
  435.      If you need to embed a literal quote character (") or a percent sign
  436.      (%) within the macro (breakpoint) body, precede the character with a
  437.      backslash character (\). To specify a literal backslash character, use
  438.      two consecutive backslashes (\\).
  439.  
  440.      If a breakpoint is being logged (refer to the built-in function
  441.      BPLOG), the action will not be executed.
  442.  
  443.      The following examples illustrate the basic use of breakpoint actions:
  444.  
  445.      BPX EIP DO "dd eax"
  446.      BPX EIP DO "data 1;dd eax"
  447.      BPMB dataaddr if (byte(*dataaddr)==1) do "? IRQL"
  448.  
  449. Conditional Breakpoints
  450.  
  451.      Conditional breakpoints provide a fast and easy way to isolate a
  452.      specific condition or state within the system or application you are
  453.      debugging. By setting a breakpoint on an instruction or memory address
  454.      and supplying a conditional expression, SoftICE will only trigger if
  455.      the breakpoint evaluates to non-zero (TRUE). Because the SoftICE
  456.      expression evaluator handles complex expressions easily, conditional
  457.      expressions take you right to the problem or situation you want to
  458.      debug with ease.
  459.  
  460.      All SoftICE breakpoint commands (BPX, BPM, BPIO, BMSG, and BPINT)
  461.      accept conditional expressions using the following syntax:
  462.  
  463.      breakpoint-command [ breakpoint options] [IF conditional expression]
  464.         [DO "commands"]
  465.  
  466.      The IF keyword, when present, is followed by any expression that you
  467.      want to be evaluated when the breakpoint is triggered. The breakpoint
  468.      will be ignored if the conditional expression is FALSE (zero). When
  469.      the conditional expression is TRUE (non-zero), SoftICE pop ups and
  470.      displays the reason for the break, which includes the conditional
  471.      expression.
  472.  
  473.      The following examples show conditional expressions used during the
  474.      development of SoftICE.
  475.  
  476.      Note: Most of these examples contain system-specific values that vary
  477.      depending on the exact version of Windows NT you are running.
  478.  
  479.    * Watch a thread being activated:
  480.  
  481.           bpx ntoskrnl!SwapContext IF (edi==0xFF8B4020)
  482.  
  483.    * Watch a thread being deactivated:
  484.  
  485.           bpx ntoskrnl!SwapContext IF (esi==0xFF8B4020)
  486.  
  487.    * Watch CSRSS HWND objects (type 1) being created:
  488.  
  489.           bpx winsrv!HMAllocObject IF (esp->c == 1)
  490.  
  491.    * Watch CSRSS thread info objects (type 6) being destroyed:
  492.  
  493.           bpx winsrv!HMFreeObject+0x25 IF (byte(esi->8) == 6)
  494.  
  495.    * Watch process object-handle-tables being created:
  496.  
  497.           bpx ntoskrnl!ExAllocatePoolWithTag IF (esp->c == æObtb')
  498.  
  499.    * Watch a thread state become terminated (enum == 4):
  500.  
  501.           bpmb _thread->29 IF byte(_thread->29) == 4)
  502.  
  503.    * Watch a heap block (230CD8) get freed:
  504.  
  505.           bpx ntddl!RtlFreeHeap IF (esp->c == 230CD8)
  506.  
  507.    * Watch a specific process make a system call:
  508.  
  509.           bpint 2E if (process == _process)
  510.  
  511.      Many of the previous examples use the thread and process intrinsic
  512.      functions provided by SoftICE. These functions refer to the active
  513.      thread or process in the operating system. In some cases, the examples
  514.      precede the function name with an underscore "_". This is a special
  515.      feature that makes it easier to refer to a dynamic value such as a
  516.      register's contents or the currently running thread or process as a
  517.      constant. The following examples should help to clarify this concept:
  518.  
  519.    * This example sets a conditional breakpoint that will be triggered if
  520.      the dynamic (run-time) value of the EAX register equals its current
  521.      value.
  522.  
  523.           bpx eip IF (eax == _eax)
  524.  
  525.      This is equivalent to:
  526.  
  527.           ? EAX
  528.           00010022
  529.           bpx eip IF (eax == 10022)
  530.  
  531.    * This example sets a conditional breakpoint that will be triggered if
  532.      the value of an executing thread's thread-id matches the thread-id of
  533.      the currently executing thread.
  534.  
  535.           bpx eip IF (tid == _tid)
  536.  
  537.      This is equivalent to:
  538.  
  539.           ? tid
  540.           8
  541.           bpx eip IF (tid == 8)
  542.  
  543.      When you precede a function name or register with an underscore in an
  544.      expression, the function is evaluated immediately and remains constant
  545.      throughout the use of that expression.
  546.  
  547. Conditional Breakpoint Count Functions
  548.  
  549.      SoftICE supports the ability to monitor and control breakpoints based
  550.      on the number of times a particular breakpoint has or has not been
  551.      triggered. You can use the following count functions in conditional
  552.      expressions:
  553.  
  554.    * BPCOUNT
  555.  
  556.    * BPMISS
  557.  
  558.    * BPTOTAL
  559.  
  560.    * BPLOG
  561.  
  562.    * BPINDEX
  563.  
  564. BPCOUNT
  565.  
  566.      The value for the BPCOUNT function is the current number of times that
  567.      the breakpoint has been evaluated as TRUE.
  568.  
  569.      Use this function to control the point at which a triggered breakpoint
  570.      causes a popup to occur. Each time the breakpoint is triggered, the
  571.      conditional expression associated with the breakpoint is evaluated. If
  572.      the condition evaluates to TRUE, the breakpoint instance count
  573.      (BPCOUNT) increments by one. If the conditional evaluates to FALSE,
  574.      the breakpoint miss instance count (BPMISS) increments by one.
  575.  
  576.      Example:
  577.  
  578.           The fifth time the breakpoint triggers, the BPCOUNT equals 5, so
  579.           the conditional expression evaluates to TRUE and SoftICE pops up.
  580.  
  581.           bpx myaddr IF (bpcount==5)
  582.  
  583.      Use BPCOUNT only on the righthand side of compound conditional
  584.      expressions for BPCOUNT to increment correctly:
  585.  
  586.      bpx myaddr if (eax==1) && (bpcount==5)
  587.  
  588.      Due to the early-out algorithm employed by the expression evaluator,
  589.      the BPCOUNT==5 expression will not be evaluated unless EAX==1. (The C
  590.      language works the same way.) Therefore, by the time BPCOUNT==5 gets
  591.      evaluated, the expression is TRUE. BPCOUNT will be incremented and if
  592.      it equals 5, the full expression evaluates to TRUE and SoftICE pops
  593.      up. If BPCOUNT != 5, the expression fails, BPMISS is incremented and
  594.      SoftICE will not pop up (although BPCOUNT is now 1 greater).
  595.  
  596.      Once the full expression returns TRUE, SoftICE pops up, and all
  597.      instance counts (BPCOUNT and BPMISS) are reset to 0.
  598.  
  599.      Note: Do not use BPCOUNT before the conditional expression, otherwise
  600.      BPCOUNT will not increment correctly:
  601.  
  602.      bpx myaddr if (bpcount==5) && (eax==1)
  603.  
  604. BPMISS
  605.  
  606.      The value for the BPMISS expression function is the current number of
  607.      times that the breakpoint was evaluated as FALSE.
  608.  
  609.      The expression function is similar to the BPCOUNT function. Use it to
  610.      specify that SoftICE pop up in situations where the breakpoint is
  611.      continually evaluating to FALSE. The value of BPMISS will always be
  612.      one less than you expect, because it is not updated until the
  613.      conditional expression is evaluated. You can use the (>=) operator to
  614.      correct this delayed update condition.
  615.  
  616.      Example:
  617.  
  618.           bpx myaddr if (eax==43) || (bpmiss>=5)
  619.  
  620.      Due to the early-out algorithm employed by the expression evaluator,
  621.      if the expression eax==43 is ever TRUE, the conditional evaluates to
  622.      TRUE and SoftICE pops up. Otherwise, BPMISS is updated each time the
  623.      conditional evaluates to FALSE. After 5 consecutive failures, the
  624.      expression evaluates to TRUE and SoftICE pops up.
  625.  
  626. BPTOTAL
  627.  
  628.      The value for the BPTOTAL expression function is the total number of
  629.      times that the breakpoint was triggered.
  630.  
  631.      Use this expression function to control the point at which a triggered
  632.      breakpoint causes a popup to occur. The value of this expression is
  633.      the total number of times the breakpoint was triggered (refer to the
  634.      Hits field in the output of the BSTAT command) over its lifetime. This
  635.      value is never cleared.
  636.  
  637.      Example:
  638.  
  639.           The first 50 times this breakpoint is triggered, the condition
  640.           evaluates to FALSE and SoftICE will not pop up. Every time after
  641.           50, the condition evaluates to TRUE, and SoftICE pops up on this
  642.           and every subsequent trap.
  643.  
  644.           bpx myaddr if (bptotal > 50)
  645.  
  646.      You can use BPTOTAL to implement functionality identical to that of
  647.      BPCOUNT. Use the modulo "%" operator as follows:
  648.  
  649.      if (!(bptotal%COUNT))
  650.  
  651.      The COUNT is the frequency with which you want the breakpoint to
  652.      trigger. If COUNT is 4, SoftICE pops up every fourth time the
  653.      breakpoint triggers.
  654.  
  655. BPLOG
  656.  
  657.      Use the BPLOG expression function to log the breakpoint to the history
  658.      buffer. SoftICE does not pop up when logged breakpoints trigger.
  659.  
  660.      Note: Actions only execute when SoftICE pops up, so using actions with
  661.      the BPLOG function is pointless.
  662.  
  663.      The BPLOG expression function always returns TRUE. It causes SoftICE
  664.      to log the breakpoint and relevant information about the breakpoint to
  665.      the SoftICE history buffer.
  666.  
  667.      Example:
  668.  
  669.           Any time the breakpoint triggers and the value of EAX equals 1,
  670.           SoftICE logs the breakpoint in the history buffer. SoftICE will
  671.           not popup.
  672.  
  673.           bpx myaddr if ((eax==1) && bplog)
  674.  
  675. BPINDEX
  676.  
  677.      Use the BPINDEX expression function to obtain the breakpoint index to
  678.      use with breakpoint actions.
  679.  
  680.      This expression function returns the index of the breakpoint that
  681.      caused SoftICE to pop up. This index is the same index used by the BL,
  682.      BC, BD, BE, BPE, BPT, and BSTAT commands. You can use this value as a
  683.      parameter to any command that is being executed as an action.
  684.  
  685.      Example:
  686.  
  687.           This example of a breakpoint action causes the BSTAT command to
  688.           lly executecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecutecu