Understanding the Program Run

Similar documents
DEBUGGING: OBSERVING AND TRACKING

0/41. Isolating Infections. Andreas Zeller. Lehrstuhl Softwaretechnik Universität des Saarlandes, Saarbrücken

Reviewing gcc, make, gdb, and Linux Editors 1

Using gdb to find the point of failure

Lecture 20. Delta Debugging Regression Testing. EE 382V Spring 2009 Software Evolution - Instructor Miryung Kim

Laboratory Assignment #4 Debugging in Eclipse CDT 1

Testing and Debugging C Programming and Software Tools. N.C. State Department of Computer Science

Computer Labs: Debugging

CSCI0330 Intro Computer Systems Doeppner. Lab 02 - Tools Lab. Due: Sunday, September 23, 2018 at 6:00 PM. 1 Introduction 0.

CSE 351. GDB Introduction

CMPSC 311- Introduction to Systems Programming Module: Debugging

Isolating and Locating Cause-Effect Chains. bug.c. What is the cause of this failure? What do we do now? Andreas Zeller

18-600: Recitation #3

Binghamton University. CS-220 Spring C Debugging Basics. No relevant text

BIL 104E Introduction to Scientific and Engineering Computing. Lecture 14

CMPSC 311- Introduction to Systems Programming Module: Debugging

How Failures Come to be. Andreas Zeller

Exercise Session 6 Computer Architecture and Systems Programming

0/38. Detecting Invariants. Andreas Zeller + Andreas Gross. Lehrstuhl Softwaretechnik Universität des Saarlandes, Saarbrücken

GDB Tutorial. A Walkthrough with Examples. CMSC Spring Last modified March 22, GDB Tutorial

Debug for GDB Users. Action Description Debug GDB $debug <program> <args> >create <program> <args>

Lab 8. Follow along with your TA as they demo GDB. Make sure you understand all of the commands, how and when to use them.

Program Design: Using the Debugger

Lecture 19. Delta Debugging Cooperative Bug Isolation. EE 382V Spring 2009 Software Evolution - Instructor Miryung Kim

Testing, Debugging, Program Verification

Debugging and Debugger. Terminology. GNU gcc and gdb. Debugging C programs in Unix and Windows Environments - Part One

Basic functions of a debugger

LAB #8. Last Survey, I promise!!! Please fill out this really quick survey about paired programming and information about your declared major and CS.

Software Engineering Testing and Debugging Debugging

CptS 360 (System Programming) Unit 4: Debugging

Today s Topic. Software Engineering Testing and Debugging Debugging. Today s Topic. The Main Steps in Systematic Debugging

LAB #8. GDB can do four main kinds of things (plus other things in support of these) to help you catch bugs in the act:

You can also start with both an executable program and a core file specified:

Today s presentation. Git gdb Project 1

Final C Details. CSE 333 Autumn 2018

CSE 374 Programming Concepts & Tools. Brandon Myers Winter 2015 Lecture 11 gdb and Debugging (Thanks to Hal Perkins)

ECE/ME/EMA/CS 759 High Performance Computing for Engineering Applications

COSC 6374 Parallel Computation. Debugging MPI applications. Edgar Gabriel. Spring 2008

Programs. Function main. C Refresher. CSCI 4061 Introduction to Operating Systems

Programming in C and C++

The Dynamic Debugger gdb

CSE 374 Programming Concepts & Tools

The First Real Bug. gdb. Computer Organization I McQuain

UNIVERSITY OF CALIFORNIA Department of Electrical Engineering and Computer Sciences Computer Science Division. P. N. Hilfinger.

1 Basic functions of a debugger

Using the Debugger. Michael Jantz Dr. Prasad Kulkarni

CS2: Debugging in Java

CS 11 C track: lecture 6

Software Engineering

CSci 4061 Introduction to Operating Systems. Programs in C/Unix

Software Development With Emacs: The Edit-Compile-Debug Cycle

Final C Details. CSE 333 Winter Teaching Assistants: Alexey Beall Renshu Gu Harshita Neti David Porter Forrest Timour Soumya Vasisht

Programming Studio #9 ECE 190

High-performance computing and programming Intro to C on Unix/Linux. Uppsala universitet

CS/COE 0449 term 2174 Lab 5: gdb

United States Naval Academy Electrical and Computer Engineering Department EC310-6 Week Midterm Spring AY2017

Problem Set 1: Unix Commands 1

CS 270 Systems Programming. Debugging Tools. CS 270: Systems Programming. Instructor: Raphael Finkel

Software Quality. Debugging " Martin Glinz. Chapter 4. Department of Informatics!

Review of Scientific Programming in C and Fortran. Michael McLennan Software Architect HUBzero Platform for Scientific Collaboration

Debugging uclinux on Coldfire

Libgdb. Version 0.3 Oct Thomas Lord

Basic C Programming (2) Bin Li Assistant Professor Dept. of Electrical, Computer and Biomedical Engineering University of Rhode Island

GDB QUICK REFERENCE GDB Version 4

GDB Tutorial. Young W. Lim Tue. Young W. Lim GDB Tutorial Tue 1 / 32

Debugging Techniques. CEFET Engineering Week

1. Allowed you to see the value of one or more variables, or 2. Indicated where you were in the execution of a program

GDB Linux GNU Linux Distribution. gdb gcc g++ -g gdb EB_01.cpp

Lecture 07 Debugging Programs with GDB

SU 2017 May 18/23 LAB 3 Bitwise operations, Program structures, Functions (pass-by-value), local vs. global variables. Debuggers

Tips on Using GDB to Track Down and Stamp Out Software Bugs

C Program Development and Debugging under Unix SEEM 3460

Princeton University COS 217: Introduction to Programming Systems GDB Tutorial and Reference

Friday, September 16, Lab Notes. Command line arguments More pre-processor options Programs: Finish Program 1, begin Program 2 due next week

Computer Labs: Debugging

CS354 gdb Tutorial Written by Chris Feilbach

Using a debugger. Segmentation fault? GDB to the rescue!

Chapter 15 Debugging

CMPT 300. Operating Systems. Brief Intro to UNIX and C

Debugging. P.Dagna, M.Cremonesi. May 2015

Intermediate Programming, Spring 2017*

CS201 Lecture 2 GDB, The C Library

CS2141 Software Development using C/C++ Debugging

CSE 124 Discussion (10/3) C/C++ Basics

Intro to Segmentation Fault Handling in Linux. By Khanh Ngo-Duy

Programming Tips for CS758/858

COSC 6374 Parallel Computation. Analytical Modeling of Parallel Programs (I) Edgar Gabriel Fall Execution Time

Recitation #12 Malloc Lab - Part 2. November 14th, 2017

Data and File Structures Laboratory

Source level debugging. October 18, 2016

Your code must have been compiled with the -g compiler option. Example:

Outline. Computer programming. Debugging. What is it. Debugging. Hints. Debugging

Procedures, Parameters, Values and Variables. Steven R. Bagley

Using the KD30 Debugger

MPATE-GE 2618: C Programming for Music Technology. Unit 4.1

Chapter 11 Introduction to Programming in C

COMP 202 Recursion. CONTENTS: Recursion. COMP Recursion 1

Program Analysis: A Hierarchy

12. Debugging. Overview. COMP1917: Computing 1. Developing Programs. The Programming Cycle. Programming cycle. Do-it-yourself debugging

A Tutorial for ECE 175

Transcription:

0/45 Understanding the Program Run Andreas Zeller Lehrstuhl Softwaretechnik Universität des Saarlandes, Saarbrücken

Isolating Failure Causes 1/45 So far, we have seen how to isolate causes in the environment of the program: Input Program Execution Erroneous code Output We treated the program as a black box, though! Observer sees failure

What we d like to see 2/45 Variable and input values Program execution Sane state Program states Erroneous code Infected state Observer sees failure

Today s Topics 3/45 Examining Program Execution. How do we know which parts of the program were executed? Examining Program State. How do we access and examine particular program states? Isolating a Specific State. Spatial focusing across the program state. Isolating the Infection. Temporal focusing across the program execution.

Examining Program Execution 4/45 Basic Question: What was executed? Simplest pattern of all: LOG EXECUTION Basic idea: Insert log statements at specific places in the progras As soon as log statement is reached, output is generated Examine sum of logs to see what was executed and what was not executed.

The No-Op test Program 5/45 Simple program test.c is supposed to print the n first primes, with n being the argument: int main(int argc, char *argv[]) { int number of primes; number of primes = atoi(argv[1]); print primes(number of primes); } Observation The program does not print anything: $ test 27 $

The No-Op test Program (2) 6/45 Hypothesis: The main function was not executed. int main(int argc, char *argv[]) { int number of primes; printf("main() was called!\n"); number of primes = atoi(argv[1]); print primes(number of primes); } Outcome main was not executed (confirmation) $ test 27 $ test invokes the system command, not our program!

Logging Data 7/45 While we re logging the location, we might as well log the current state: int main(int argc, char *argv[]) { int number of primes; number of primes = atoi(argv[1]); printf("main(): number of primes = %d\n", number of primes); print primes(number of primes); printf("main(): returning\n") } Logging is the easiest and most common debugging technique!

Logging in Practice 8/45 Use standard formats. This applies to events ( prefix each line with time ) applies to data ( output all dates in Y-M-D format ) is best achieved by using dedicated logging functions. Make logging optional. For efficiency, logging is typically turned off in production code. Allow for variable granularity. Depending on the problem you are working on, it may be helpful to focus on specific levels of detail.

Simple Macros for Logging 9/45 We use LOG(("number_of_primes = %d", number_of_primes)) to get number_of_primes = 3 Definition: #define LOG(args) printf args In practice: dedicated logging function instead of printf

Extra Logging Information 10/45 We use LOG(("number_of_primes = %d", number_of_primes)) to get main.c:3: number_of_primes = 3 Definition: #define LOG(args) \ printf("%s:%d: ", FILE, LINE ), \ printf args, \ printf("\n") This scheme can easily be extended to log date/time, etc.

Optional Logging 11/45 We turn logging off at compile time using the NDEBUG ( No Debugging ) macro $ gcc -DNDEBUG -o mytest test.c Definition: #ifndef NDEBUG #define LOG(args) as before #else #define LOG(args) #endif If NDEBUG is set, LOG(args) compiles to a no-op

Logging Granularity 12/45 We turn logging on and off at runtime using a LOG FILES environment variable: $ LOG FILES="main.c debug-*.c" mytest Definition: #define LOG(args) \ do we log this( FILE ) && \ (printf("%s:%d: ", FILE, LINE ), \ printf args, \ printf("\n")) Complex macro definitions can easily be turned into an appropriate function.

Lots of Logs 13/45 Problem: Lots and lots of logging code can easily clutter the real program code. Delete logging code when debugging is finished. Problem: When do we know that debugging is finished? Use a debugger instead. Problem: Have to recreate everything every time. Encapsulate logging within an aspect. An aspect is a separate syntactical entity that can be interwoven with the program (i.e. it is optional).

Logging with Aspects 14/45 Aspects give very elegant ways to handle logging: public aspect Tracer { pointcut allmethods(): call(public * Article.*(..)); before(): allmethods() { System.out.println ("Entering " + thisjoinpoint); } after(): allmethods() { System.out.println ("Leaving " + thisjoinpoint); } }

Even better Logging 15/45 Current trends in logging: Insert logging code automatically (just as with a tracing aspect) Visualize log results (rather than simply printing them) Search for patterns (such as this sequence of function calls occurs n times ) and deviations

Tracing with Jinsight 16/45

Persistent vs. Transient Logging 17/45 Logging has an advantage and a disadvantage: Logging is compiled within the program Logging is compiled within the program If I want a more transient approach, I use a debugger instead.

Basic Debugger Facilities 18/45 A debugger allows to Start your program, specifying anything that might affect its behavior. Make your program stop on specified conditions. Examine what has happened when your program has stopped. Change things in your program, so you can experiment with correcting the effects of one bug and go on to learn about another. Source: gdb(1) manual page

Examining Program Execution 19/45 How do we know which parts of the program were executed? A breakpoint makes the program stop as soon as it reaches a specific location. $ gdb sample (gdb) break main Breakpoint 1 in main (gdb) The program will stop as soon as main is reached (formally: the program counter (PC) is main)

Breakpoints in Detail 20/45 Formally, a breakpoint defines a predicate on the program state the program stops as soon as the predicate holds. A predicate like the current PC is main is easy to check: If the program is stored in RAM, we can replace the instruction at main with a break instruction (when the breakpoint is reached, the original instruction is restored) Many processors have debugging registers which interrupt execution as soon as the PC is equal to a registered value Many debuggers support only simple breakpoints the PC is x.

Breakpoints and Watchpoints 21/45 Some debuggers provide additional predicates especially predicates on data. A GDB watchpoint will interrupt the program as soon as a specific variable changes its value: (gdb) watch a Hardware watchpoint 1: a (gdb) continue Old value = (int *) 0xbffff518 New value = (int *) 0x8049850 (gdb)

Watchpoints in Detail 22/45 Watchpoints can be arbitrarily complex: (gdb) watch f(x)!= 42 will stop as soon as f(x) changes its value Watchpoints can simulate breakpoints: (gdb) watch $pc!= main will stop as soon as the program counter reaches main No support for is called by, within or other useful predicates from aspect-oriented programming : (

Watchpoints in Detail (2) 23/45 Watchpoints are typically expensive: Some processors have debugging data registers which interrupt execution as soon as the value at the registered address changes its value. This is efficient, but works only for simple values (and the program counter). If no such registers exist, or if the watched expression must be computed, the debugger must inquire the data after each single instruction, reducing speed to 1/1000.

Conditional Breakpoints 24/45 Conditional breakpoints allow users to check predicates only at specific locations i.e. when the PC reaches a certain value. (gdb) break print_primes if n_primes == 2 Breakpoint 1 at print_primes (gdb) The program will stop if the PC is print primes and n primes is 2. Due to the PC checking, this can again be implemented efficiently.

Conditional Breakpoints (2) 25/45 Conditional breakpoints can be used to realize assertions on-the-fly: Rather than writing int foo() { assert (a > 0);... one could set a breakpoint (gdb) break foo if a <= 0 (gdb) These assertions on-the-fly are transient (not sure whether this is a good thing...)

Breakpoints and Predicates 26/45 Overview of breakpoint commands: Type GDB Command Predicate Breakpoint break location PC = location Watchpoint watch expr expr changes Cond. bp break location if expr PC = location expr The debugger also automatically stops the program on user interrupts (Ctrl+C) if it receives a fatal signal if an uncaught exception is thrown

Examining the Stack 27/45 Among the first tasks to do when a program stops is to examine the current backtrace the stack of calling functions. (gdb) run Starting program: sample Breakpoint 1, shell_sort (a=0x8049850, size=1) at sample.c:9 9 int h = 1; (gdb) where #0 shell_sort (a=0x8049850, size=1) at sample.c:9 #1 main (argc=1, argv=0xbffff564) at sample.c:35 #2 libc_start_main () from /lib/libc.so.6 (gdb)

Examining Program Data 28/45 Once a program has stopped, we can examine its data in the state where the program stopped. All debuggers can print single variables: (gdb) print a[0] $1 = 0 (gdb) Most debuggers also support expressions: (gdb) print a[size - 1] $2 = 0 (gdb)

Examining Program Data (2) 29/45 Some debuggers also support function calls: (gdb) print main(argc, argv) $3 = 0 (gdb) Method invocations are also possible: (gdb) print c1.operator==(c2) $4 = false (gdb) If execution stops during the evaluation of the expression, interesting things can happen : )

Examining Program Data (2) 30/45 To access the variables of a calling function, one can navigate through the backtrace: (gdb) frame #0 shell_sort (a=0x8049850, size=4) at sample.c:9 (gdb) info locals i = 1073834752 j = 1074077312 h = 1961 (gdb) up #1 0x8048647 in main (argc=4, argv=0xbffff544) at sample.c:35 (gdb) info locals a = (int *) 0x8049850 i = 3 (gdb)

Resuming Execution 31/45 After one is done examining the program state, one can resume execution (until the next stopping condition is reached): (gdb) continue Program exited normally. (gdb) Oops obviously, we should have set another breakpoint!

Stepping through the Program 32/45 A common task is to execute the program until the next statement is reached: (gdb) run 7 8 9 Breakpoint 1, shell_sort (a=0x8049850, size=4) at sample.c:9 9 int h = 1; (gdb) step 11 h = h * 3 + 1; (gdb) step 12 } while (h <= size); (gdb)

Stepping through the Program (2) 33/45 Several commands are available to step: step PC reaches next executed statement, maybe in different function next PC reaches next executed statement in same function or current function returns until PC reaches line greater than the current or current function returns finish current function returns continue resume execution unconditionally All these commands are realized using temporary breakpoints at the appropriate locations.

Logging Data 34/45 Using a debugger, one can also log values automatically. display variable prints variable with each GDB prompt. (gdb) display a a = 1 (gdb) next a = 2 (gdb) next a = 3 (gdb) continue Breakpoint 1, shell_sort (a=0x8049850, size=4) at sample.c:9 a = 4 (gdb)

Logging Data (2) 35/45 Alternate idea associate breakpoint with commands (gdb) break 16 Breakpoint 1 at file sample.c, line 16. (gdb) commands Type commands for when breakpoint 1 is hit, one per line. End with a line saying just "end". >print i >cont >end (gdb)

Logging Data (3) 36/45 (gdb) run Starting program: sample 7 8 9 Breakpoint 1 at sample.c:17 17 int v = a[i]; $1 = 1 Breakpoint 1 at sample.c:17 17 int v = a[i]; $2 = 2 Breakpoint 1 at sample.c:17 17 int v = a[i]; $3 = 3...

Logging Data (4) 37/45 Nicer alternative, using silent and printf: (gdb) commands 1 Type commands for when breakpoint 1 is hit, one per line. End with a line saying just "end". >silent >printf "i = %d\n", i >cont >end (gdb) run Starting program: sample 7 8 9 i = 1 i = 2 i = 3...

DDD A Graphical User Interface 38/45

Logging vs. Debugger 39/45 Examining Program Execution. Logging: Close to the code, persistent Debugger: Tedious, interactive, but versatile Examining Program State. Logging: Close to the code, persistent Debugger: Tedious, interactive, very versatile

Spatial and Temporal Focusing 40/45 Variable and input values Program execution Sane state Program states Erroneous code Infected state Observer sees failure

Spatial focusing 41/45 Basic idea: Separate sane state (= as intended) from infected state (= not as intended) Use logging (or a debugger) to access state Use assertions (or likewise debugger techniques) to separate sane from infected state

Temporal focusing 42/45 Basic idea: identify the moment in time where the state becomes infected Use logging (or a debugger) to access execution Use binary search to find out the moment in time where the state first became infected Trace back possible origins of the infection To be addressed in remainder of the course!

Concepts 43/45 Logging is a simple technique to understand what was executed what states the program was in Programmers use or define dedicated logging facilities Aspects allow encapsulating logging in own syntactical entities

Concepts (2) 44/45 Debuggers allow a versatile and transient access to execution and data The program can be stopped as soon as a specific predicate holds (typically PC = location) In a stopped program, we can examine arbitrary data Assertions and logging can be added on the fly

Concepts (3) 45/45 Spatial focusing means to separate the state into sane (= as intended) and infected Temporal focusing means to isolate the moment in time where the infection occurs All this must be (and can be) automated!