2

Don't be confused by a title of a question. Here is an explanation.

Let's take Intel Pin. They claim that

The best way to think about Pin is as a "just in time" (JIT) compiler. The input to this compiler is not bytecode, however, but a regular executable. Pin intercepts the execution of the first instruction of the executable and generates ("compiles") new code for the straight line code sequence starting at this instruction. It then transfers control to the generated sequence.

However, software breakpoint (according to Reversing: Secrets of Reverse Engineering by Eldad Eilam) is:

Software breakpoints are instructions added into the program’s code by the debugger at runtime. These instructions make the processor pause program execution and transfer control to the debugger when they are reached during execution.

Basically both Intel PIN and e.g. OllyDBG does roughly similar things: altering the execution flow by inserting custom instruction. I know, that with PIN you can do much more then just pause under a certain condition, but it is not the point.

So, my question is what is the key difference between JIT compilation (as in Intel PIN) and Software breakpoints (as in OllyDBG or any other debugger)?

2
  • 1
    I think JIT is not relevant here. Pintool injects code into running process, it can also use software breakpoints. Am i wrong? Commented Feb 10, 2017 at 19:15
  • No, after NirIzr's answer I agree with you. My first topic title was not really precise.
    – aGGeRReS
    Commented Feb 10, 2017 at 23:12

1 Answer 1

2

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:

JIT Compilation

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.

Software breakpoint

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.

Binary Instrumentation (Pintool)

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.

4
  • Thank you for that great answer. Here is my short summary (to check if I understood it correctly): Software breakpoints use specific CPU instruction to interrupt execution flow (as I understand it substitutes a particular command with 0x55), while Binary Instrumentation modifies executable code more significantly. So can we say, that Software breakpoint is just a special case of binary instrumentation?
    – aGGeRReS
    Commented Feb 10, 2017 at 23:10
  • 1
    0xCC, not 0x55. Software breakpoints are not considered a simple case of binary instrumentation because placing those usually lacks the heavy part of processing a binary and generating new executable code. Youre correct on everything else.
    – NirIzr
    Commented Feb 11, 2017 at 0:20
  • Modern CPUs support branch tracing. That way to you don't have to modify anything to log all branches and their targets.
    – mrexodia
    Commented Feb 12, 2017 at 12:02
  • Yes. That was merely an example.
    – NirIzr
    Commented Feb 12, 2017 at 13:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.