Intel Pintool is not a JIT compiler. The explanation you quote just uses an analogy to JIT compilation, as there are logical similarities. IMHO this is not a well thought out analogy, and should be taken very lightly.
I'll explain the three concepts in detail:
Indeed, the concept of JIT compilation is not really relevant to the question, but I'll go over it just the same:
JIT compilation is mostly used as a performance improvement for interpreted languages, but some more advanced languages use it (examples are .Net and java).
When a non-compiled code is executed, there's basically a loop processing each bytecode in a sequence (similar to how a Processor executes instructions one after the other). That loop basically implements byte code instructions to CPU instructions, modifying a state context (similar to CPU registers, only usually a lot bigger and higher-level).
That process is slow compared to CPU instructions, and usually for no good reason - that was how interpreters were designed. Here comes JIT.
This is basically saying that instead of implementing a loop processing each bytecode instruction, it is possible for that loop to generate CPU instructions the first time it runs, and just execute those. To simplify things, JIT is a process of translating the language's bytecode to the CPU's instruction set just before executing the code, letting the CPU instructions run instead of the interpreter loop. Usually the compiled code is cached to it won't be compiled again.
A software breakpoint is a specific instruction (in x86: int 3
, encoded both as 0xcc
and 0xcd0x03
) that tells the CPU the user (in CPU terms, this usually means a developer) would like to know whenever it is executed and suspend the execution for further inspection. When it is hit an interrupt handling mechanism it triggered and the execution of the process is suspended by a debugger handling that interrupt. debuggers then usually let the developer inspect the code, modify it, and then resume execution. A debugger sets a software breakpoint by replacing a single instruction (or part of it) with a the software breakpoint interrupt, and sets it back to the original instruction when it later resumes execution.
With Binary Instrumentation, a tool such as Pintool processes the code within a binary executable (similarly to how a JIT compiler processes a bytecode or script) and creates a "fixedup" or modified executable code, by inserting multiple types of additional code. This is usually done when breakpoints are not enough, or when you want to analyze a lot of an executable. Examples include modifying all jump
instructions (say, to log the source and target of all jumps, for example).
As you said software breakpoints are quite limited compared to the abilities a binary instrumentation engine provides, so I focused on the technical implementation rather than the advantages of the two.