Despite Joel's missive that software rewrites are to be avoided under pain of death, it is still fairly common place. A lot of the existing software is good, but here and there, parts of it niggle, so for a while, you continue along your way.
"You can't polish a turd, but you can roll it in glitter"
So you tweak it here and there in a haphazard fashion - tinkering round the edges because you don't want to dig into the innards. Time passes, technical debt, software entropy - you get the picture.
This, until someone suited and booted says: "No more". Perhaps the language has fallen out of vogue, or has been superseeded. Now, which of the following (or mix of) can be used to aid the process? Are there any other methods? What other factors are there?
EDIT: I'm not looking for an ever increasing pick-and-mix list of approaches here - more a cohesive toolkit.
Line by line
If the project isn't too large, you may be able to look at the code line by line to get a feel for what it is doing.
Functional clone (dev view)
As a developer of the previous incarnation, you may have a spin on what the various functions are so you design from there.
Functional clone (user view)
The user (or team of), get together and decide which features are the most important and which can be parked until a later phase or scrapped.
Forensics
3rd party tools are used to extract the module names, method names and data structures.
Path analysis
Code is added (or perhaps existing audit code leveraged) to see which are the most commonly used parts of the program and go from there.