Categories
patterns

Pattern Patter: Post-Process Binaries

Summary: Add capabilities to a language without extending the language. [Architecture Pattern]

Example

You may have a source language that doesn’t provide a particular capability. You can’t or won’t change the source language. (Perhaps you can’t change the language; perhaps making the user recompile just to acquire that capability is too time-consuming.)

Forces

  • You want to add a generic capability without requiring its presence to be (too) visible in the source language.
  • You can afford to work in both the source and object levels.
  • You can map from the object level back to the source (as far as your capability is concerned). Or perhaps the capability can be interpreted independently of the source representation.

Resolution

Insert the capability at the object level. Provide tools to map back to the source level if necessary.

Discussion

  • The capability may interact with optimization; you need to ensure that compiler optimizations will not significantly interfere with your capability. For example, a tool to log procedure calls might not detect inlined calls.
  • The mapping to the source level is often problematic.
  • Adding the capability will interfere with the usual timing of operations.

Other Uses

  • A debugger might cause a “break on call” by replacing a procedure call with an interrupt or a call to the deugger’s own procedures. [ASPLOS ref on s/w breakpoints?]
  • The Purify tool (from Rational) monitors a program for illegal data access by replacing the user’s standard libraries and by modifying data access code in place.
  • The ObjectStore database (from ODI) modifies C++ or Java object files to add persistence. This case is interesting because they can use a fairly non-intrusive change at the source level (e.g., inheriting from a marker interface), then use that change as an indicator of which objects to modify.

[Written 12-4-97; revised 1-6-98.]