Techniques for Diagnosing Software Faults