I tried dinking around with the debug-function stuff to get a better handle on what was actually in the function, and I'm a bit confused as to what functions actually correspond to-- I assume just some arbitrary range of code (where did the name debug-FUNCTION come from, anyway, seeing that you can't call them...)? The story is that each debug-function really does correspond to a LAMBDA in the compiler's front-end representation. The functions are really callable, but only via block-compiled references at compile time. In a simple case, I have a function FOO and its :EXTERNAL entry point. The XEP is responsible for doing function type and argument syntax checking (the OPTIMIZE-INTERFACE declaration really controls policy in the XEP). Once inside a block-compilation unit (or component), calls are direct jumps using the local call mechanism. Factoring out the argument checking into a separate function provides a clean way to avoid doing this checking in local calls. Functions with non-fixed argument counts are compiled with an arbitrarily large number of helper functions, in addition to the main function. Currently I get somewhat reasonable results by looking for debug-functions with the same name as the function (though I'm not sure if there will always be a 1-1 mapping) and then picking off: zero-or-one :external DF zero-or-more (not nil or :external) DF's zero-or-one NIL DF zero-or-more (not nil or :external) DF's The should work pretty well, though it may print unrelated stuff in block compilations. There should really be better information about what all the DFs in a component are doing. At the very least, there should be a mapping between the XEP and the main (NIL) function. One problem is that all string-named functions have the same name, even though they might come from different DEFUNs. This is rather non-intuitive anyway, and should be fixed. -- I tried to start looking code-instruction offset matched, but it seems to be randomly off by 4 bytes in the function-map), Not sure what you are saying. This doesn't work for things with the elsewhere-pc bit, I'll try to clarify how the function map and elsewhere code are supposed to relate. Every internal compiler function (and hence DF) has two chunks of code: normal and elsewhere. When producing the code object, the compiler emits the normal code for each DF contiguously, but with no particular ordering of DFs. After all the normal code in the component comes all the elsewhere code. The elsewhere chunks for each function are concatenated in exactly the same (arbitrary) order as the normal code in the DF. To tell whether a given code location lies in elsewhere code, the DI code sees if the location is >= to the COMPILED-DEBUG-FUNCTION-ELSEWHERE-START of the first DF in the function map. If so, it locates the DF which contains it by doing a search using the C-D-F-ELSEWHERE-START instead of the normal code starts. Elsewhere code does not have a separate debug function; every DF has two chunks of code, normal and elsewhere. All the elsewhere code for a DF is in a single DEBUG-BLOCK which has the elsewhere-p flag set. This debug-block is rather anomalous in that it doesn't in any way represent a basic block in the code; it has no recorced successors, etc. The DFs do seem useful for picking up the other random info (e.g., the variable mappings). Is there really just one register for a given lisp variable throughout the whole DF (which seem awfully long)? Yes, there is just one register, and yes, this is probably awfully long. This was supposed to be a simple, throw-away register allocator, which I would replace with a real one :-). Of course, making it more general would make the debug-info even more hairy. Rob