Modifying programs, libraries and operating systems becomes a difficult problem when the source code is not available, and this is a common situation. Vendors are quite reticent to give away the source code of their applications and/or operating systems. On the other hand, there are many situations in which these modifications would be very useful. Let us examine some examples.
Tracing and monitoring applications is a common technique used to learn the behavior of applications. To perform this task, some code has to be added to the program to trace or monitor the desired events. If the source code is not available, there is no easy way to do it.
Another problem arises when trying to enhance proprietary applications to take advantage of parallel resources such as multiple CPUs. Let us suppose an application that invokes many time-consuming operations from a sequential mathematical library, for example large FFTs. If we do not have the source code, changing the implementation of the FFT to make it a parallel one, would probably mean to write a whole new library. If we only want to enhance the FFT, it is going to be very difficult without the source code of the application or the library.
If we focus our attention on the operating system execution environment, it is very difficult to modify its functionality (for instance, to build a new file system) without OS support. Even if there is some OS support, we will probably need the help of the system administrator to install our enhancement. There is no easy way to do a rapid prototyping that is being used by many applications without the help of the system administrator.
Finally, sometimes we would like to modify an application to send and receive the data in an encrypted form. If we do not have the source code of the application or library, this modification will be a big problem.
In this paper, we present a tool that can be used to solve all the above problems. This tool provides transparent user-level extensibility and flexible composition within applications. This allows any user to load new code and to interpose it between the call and the definition of functions, making possible to modify or extend programs without rebuilding them. We also describe several examples in which we use the tool to solve the aforementioned problems.
This paper is structured as follows. Section 2 gives an overview of our approach to dynamic extension and flexible composition, describing the framework and the tool. Section 3 discusses performance issues and presents an evaluation. Section 4 contains the examples. Section 5 reviews related work and, finally, Section 6 summarizes and concludes the paper.