hi, I am looking into implementing a new instrumentation pass in gcc called a "globalizer" and I would be really grateful for feedback on whether or not such a pass could be considered for inclusion (from a purely technical perspective).
1) Rationale ------------ I work on network simulation tools. These tools are used to describe network topologies, simulate traffic flows through them and analyze the behavior of the network during the simulation. One of the things the network guys would like to be able to do is run a number of instances of an existing user-space routing daemon in the simulator. To be able to do this, you need, among others, to run multiple virtual processes in a single user-space process and each of these virtual processes must access a private version of its global variables (static or not). In a perfect world, we should be able to deal correctly with TLS variables and make each simulation process maintain as many instances of its TLS variables as needed. TLS variables aside, there are a number of ways to implement that globalization process: 1) implement a C/C++ globalizer which edits the source code. 2) on ELF systems, recompile all the code as PIC and play crazy tricks with the dynamic loader 3) add an option to the compiler to perform the transformations done by 1). 1) has already been implemented but only deals with C source code. Adding support for C++ is a matter of ripping out an existing c++ parser and hack transformations in it. I feel this path is a dead end so, I would like to avoid going down that road 2) I implemented this solution but it is pretty icky, and requires hacking a copy of the glibc dynamic loader. There are also a bunch of issues related to debugging (gdb needs to be taught about multiple versions of the same function in memory at different virtual addresses) which make this solution rather unatractive. So, I am looking into getting 3) to work 2) Proposed pass solution: -------------------------- The idea is to change the way the address of a global variable is calculated: rather than merely access a memory area directly or through the GOT, we need to add another level of indirection. The simplest way to add another level of indirection is to replace every declaration and definition of a static variable by another static variable which would be an array of the original variables: static int a; void foo (void) { a = 1; } would be transformed into: static int a[MAX_PROCESS_NUMBER]; void foo (void) { a[process_id] = 1; } Another solution would be to do something like this: extern void *magic_function (void *variable_uid); static int a; void foo (void) { void *ptr = magic_function (&a); int *pa = (int *)ptr; *pa = 1; } and then make the user provide magic_function at link time, just like __cyg_profile_func_enter. magic_function would need to lookup the variable uniquely identified by its address within the context of the current simulation process. This solution solves the problem of a fixed-size array (no need to rebuild when the number of processes changes) because it is then up to the simulator's magic_function to do the right thing. However, this would be much slower. Would the speed difference really matter in my use-cases ? I doubt it. 3) questions ------------ So, I have many questions but the main one is that I would like to know whether or not there would be interest in integrating such a pass in gcc proper or if this is deemed to be too domain-specific to be considered. thank you, Mathieu