Last Updated: 2024-09-30 Mon 10:21

CMSC216 Lab05: GDB Basics and Bit Masking

CODE DISTRIBUTION: lab05-code.zip

CHANGELOG:

Mon Sep 30 10:16:16 AM EDT 2024

Post 592 identified problems with a new version of the testing script testy on GRACE. The fix for now is to revert to an older version of testy: remove the current testy and download a past version of testy into the lab directory for use in the lab. The following two commands should do this

  lab05>> rm testy
  lab05>> wget https://www.cs.umd.edu/~profk/216/testy

The working version of testy is now in the current lab codepack so those just starting the lab should not need to do this.

1 Rationale

Debuggers are an essential tool for any serious coder. They provide the ability to stop a program at any point and inspect its state by examining variables, traversing memory, and showing stack traces. This exercise briefly surveys basic debugger capabilities by applying GDB to a small program drawn from the current programming project. Determining the behavior and required inputs for the program is made immensely easier through the use of the debugger.

Certain applications utilize bits at an individual level. This is enabled by support for bit-level operations in most processors which are presented in C programs as bit-wise logical and shift operations. This lab explores the basic mechanics of these operations in preparation for project work which will provide a concrete application for them.

Associated Reading

CSCI 2021 Quick Guide to gdb: The GNU Debugger: Page describing how to start the debugger, a sample session using puzzlebox, an overview of the most common commands.

Bryant and O'Hallaron Sections 2.1.6 to 2.1.9 discuss bit-level operations in C. Numerous examples are provided that complement material presented here.

Grading Policy

Credit for this exercise is earned by completing the code/asnwers here and submitting a Zip of the work to Gradescope. Students are responsible to check that the results produced locally via make test are reflected on Gradescope after submitting their completed Zip. Successful completion earns 1 Engagement Point.

Lab Exercises are open resource/open collaboration and students are encouraged to cooperate on labs. Students may submit work as groups of up to 5 to Gradescope: one person submits then adds the names of their group members to the submission.

See the full policies in the course syllabus.

2 Codepack

The codepack for this lab is linked at the top of this document. Always download it and unzip/unpack it. It should contain the following files which are briefly described.

File Use Description
QUESTIONS.txt EDIT Questions to answer: fill in the multiple choice selections in this file.
phase03.c Analyze C program that emulating part of P2's puzzlebox
masking.c EDIT C file to edit and complete; TODO sections are marked in the code
input.txt EDIT Input file for phase03 which should be edited to contain correct inputs.
Makefile Build Enables make test and make zip
QUESTIONS.txt.bk Backup Backup copy of the original file to help revert if needed
QUESTIONS.md5 Testing Checksum for answers in questions file
test_quiz_filter Testing Filter to extract answers from Questions file, used in testing
test_lab05.org Testing Tests for this exercise
testy Testing Test running scripts

3 QUESTIONS.txt File Contents

Below are the contents of the QUESTIONS.txt file for the exercise. Follow the instructions in it to complete the QUIZ and CODE questions for the exrecise.

                           _________________

                            LAB05 QUESTIONS
                           _________________





Exercise Instructions
=====================

  Follow the instructions below to experiment with topics related to
  this exercise.
  - For sections marked QUIZ, fill in an (X) for the appropriate
    response in this file. Use the command `make test-quiz' to see if
    all of your answers are correct.
  - For sections marked CODE, complete the code indicated. Use the
    command `make test-code' to check if your code is complete.
  - DO NOT CHANGE any parts of this file except the QUIZ sections as it
    may interfere with the tests otherwise.
  - If your `QUESTIONS.txt' file seems corrupted, restore it by copying
    over the `QUESTIONS.txt.bk' backup file.
  - When you complete the exercises, check your answers with `make test'
    and if all is well, create a zip file with `make zip' and upload it
    to Gradescope. Ensure that the Autograder there reflects your local
    results.
  - IF YOU WORK IN A GROUP only one member needs to submit and then add
    the names of their group.


GDB QUIZ gdb basics and phase03.c
=================================

Starting Up
~~~~~~~~~~~

  After starting up GDB with the `phase03' program, the `run' command
  will yield the following output
  ,----
  | > gdb ./phase03
  | ...
  | 
  | (gdb) run
  | Starting program: ./phase03 
  | usage: ./phase03 <infile>
  | [Inferior 1 (process 1943881) exited with code 01]
  `----
  which means that the `phase03' program wants a command line
  argument. How does one accomplish this in GDB?
  - ( ) Use the command `set args input.txt' once and then each `run'
    will use those arguments
  - ( ) Use the command `run input.txt' each time you run
  - ( ) Either of the above will work
  - ( ) Start GDB as `gdb ./phase03 input.txt'


Setting a Breakpoint
~~~~~~~~~~~~~~~~~~~~

  Which of the following commands will set a breakpoint in GDB at the
  line that reads `int hit = shot ^ targ;'?
  - ( ) `break int hit = shot ^ targ'
  - ( ) `break phase03'
  - ( ) `break phase03.c:34'
  - ( ) `break next hit'

  After hitting the specified breakpoint, which of the following GDB
  commands will advance to the next **breakpoint** that is set?
  - ( ) `next'
  - ( ) `continue'
  - ( ) `run'
  - ( ) `advance'


next command in gdb
~~~~~~~~~~~~~~~~~~~

  During a debugging, the debugger has `phase03' stopped at the line
  indicated below via a `>' character.
  ,----
  | /// INITIAL ///
  |   void phase02(){
  |     int a = atoi(next_input());
  | >   int b = atoi(next_input());
  |     int c = atoi(next_input());
  | ....
  | 
  |   char *next_input(){
  |     input_idx++;
  |     int ret = fscanf(input_fh, "%s", inputs[input_idx]);
  | ...
  | 
  `----

  When the `next' command is executed by GDB, then the debugger executes
  some code and leaves the state of the running program in one of the
  following positions:

  ,----
  | /// OPTION A ///
  |   void phase02(){
  |     int a = atoi(next_input());
  |     int b = atoi(next_input());
  | >   int c = atoi(next_input());
  | ....
  | 
  |   char *next_input(){
  |     input_idx++;
  |     int ret = fscanf(input_fh, "%s", inputs[input_idx]);
  | ...
  | 
  | /// OPTION B ///
  |   void phase02(){
  |     int a = atoi(next_input());
  | >   int b = atoi(next_input());
  |     int c = atoi(next_input());
  | ....
  | 
  |   char *next_input(){
  |     input_idx++;
  |     int ret = fscanf(input_fh, "%s", inputs[input_idx]);
  | ...
  | 
  | /// OPTION C ///
  |   void phase02(){
  |     int a = atoi(next_input());
  |     int b = atoi(next_input());
  |     int c = atoi(next_input());
  | ....
  | 
  |   char *next_input(){
  | >   input_idx++;
  |     int ret = fscanf(input_fh, "%s", inputs[input_idx]);
  | ...
  `----

  After executing `next', which option correctly indicates where GDB
  will get control back?
  - ( ) OPTION A because `next' moves to the next line of code executing
    all functions and operations on a given line.
  - ( ) OPTION B because `next' executes the next operation and
    completes it which will be the `next_input()' function but the
    `atoi()' function will not be run
  - ( ) OPTION C because `next' steps into functions and executes the
    next operation which is to start running the `next_input()'
    function.


step command in gdb
~~~~~~~~~~~~~~~~~~~

  Instead of using the `next' command in the above example, what if the
  `step' command was used instead from the `INITIAL' position? Which
  `OPTION' represents the code position GDB would be at after `step'?

  - ( ) OPTION A because `step' moves to the next line of code executing
    all functions and operations on a given line.
  - ( ) OPTION B because `step' executes the next operation and
    completes it which will be the `next_input()' function but the
    `atoi()' function will not be run
  - ( ) OPTION C because `step' steps into functions and executes the
    next operation which is to start running the `next_input()'
    function.


GDB CODE input.txt for phase03
==============================

  The mock `phase03' program can be compiled via `make' and run via
  ,----
  | > ./phase03 input.txt
  `----


  Use `gdb' and analyze what inputs are required in the file `input.txt'
  in order to "pass" the phase. A correct run yields the output:
  ,----
  | > ./phase03 input.txt
  | Running mock Phase03
  | Right on target: nice shootin' bitslinger!
  | Phase complete
  `----
  which is checked for in the CODE tests.

  Test that the code behaves correctly via the command
  ,----
  | make test-code testnum=1
  `----


Hints to Determine the Input
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  - There are 4 input numbers required for the phase and these are
    extracted from the input.txt file
  - There is a variable called `targ' which is important to examine; you
    may wish to examine its value carefully using gdb's `print' command;
    set a breakpoint after `targ' has its value set and try the
    following commands
    ,----
    |   gdb> print targ     # print as decimal int
    |   gdb> print/x targ   # print as hexadecimal
    |   gdb> print/t targ   # print in binary
    `----


The Elephant in the Room
========================

  While `phase03.c' can provide practice setting breakpoints and
  stepping execution, the most interesting aspect of it is the use of
  bit-level operations like shifts (left shift: `a << b') and
  bitwise-and (a & b).  Without a reasonable understanding of these
  operations, it will be difficult to understand the inputs required to
  satisfy the input constraints.  The next set of exercises discusses
  bitwise operations and their effects.


MASKING QUIZ mask.c
===================

  Study the code in `masking.c' which uses a number of bit-wise
  operations that have recently been discussed in lecture. These
  include:
  ,----
  | | Operation | Description          |
  | |-----------+----------------------|
  | | x & y     | Bit-wise And         |
  | | x | y     | Bit-wise Or          |
  | | x ^ y     | Bit-wise Xor         |
  | | ~x        | Bit-wise inversion   |
  | | x << y    | Bit-wise Left-shift  |
  | | x >> y    | Bit-wise Right-shift |
  `----
  Study the examples provided in `masking.c' and ensure you understand
  their meaning according to the context provided. Then answer the
  following questions.


Terminology
~~~~~~~~~~~

  - "Setting" a given bit means to place a 1 that position; "Set bit 7"
    means to ensure that the 7th bit from the left is a 1
  - "Clearing" a give bit means to place a 0 at that position; "Clear
    bit 7" means to ensure that the 7th bit from the left is a 0


Shift with Or
~~~~~~~~~~~~~

  What is the effect of the following line of code:
  ,----
  | x = x | (1 << 19);
  `----

  - ( ) Changes `x' so that only its 19th bit is a 1, all other bits are
    0.
  - ( ) Changes `x' so that only its 19th bit is a 0, all other bits are
    unchanged.
  - ( ) Changes `x' so that its 19th bit is set to 1, all other bits
    unchanged.
  - ( ) Changes `x' so that its bits are shifted left by 19 places.


Shift with Or with Pattern
~~~~~~~~~~~~~~~~~~~~~~~~~~

  If `x' is cleared (value all 0's), what is the effect of the following
  line of code:
  ,----
  | x = x | (0b110101 << 8);
  `----

  - ( ) Sets the bits of `x' to the given pattern `0b110101' starting
    with the 8th position.
  - ( ) Checks that `x' has the given pattern `0b110101' starting with
    the 8th position.
  - ( ) Copies the given pattern `0b110101' 8 times throughout `x'
  - ( ) Adds 53 on the value of `x' faster than normal addition.


Shift with Invert with And
~~~~~~~~~~~~~~~~~~~~~~~~~~

  What is the effect of the following line of code:
  ,----
  | x = x & ~(1 << 8);
  `----

  - ( ) Changes `x' so that only its 8th bit is a 1, all other bits are
    0.
  - ( ) Changes `x' so that only its 8th bit is a 0, all other bits are
    unchanged.
  - ( ) Changes `x' so that its 8th bit is set to 1, all other bits
    unchanged.
  - ( ) Changes `x' so that its bits are shifted left by 8 places.


Shift with And
~~~~~~~~~~~~~~

  What is the effect of the following line of code:
  ,----
  | if( x & (1 << 13) ){ ... }
  `----

  - ( ) Conditionally execute only if the 13th bit of `x' is 0 and set
    that bit subsequently.
  - ( ) Conditionally execute only if the 13th bit of `x' is 0 but leave
    `x' unchanged.
  - ( ) Conditionally execute only if the 13th bit of `x' is 1 and set
    that bit subsequently.
  - ( ) Conditionally execute only if the 13th bit of `x' is 1 but leave
    `x' unchanged.


MASKING CODE Complete masking.c
===============================

  Complete the TODO items in the `masking.c' file so that the missing
  blocks produce the effect mentioned in the `printf()' statements.

  Test that the code behaves correctly via the command
  ,----
  | make test-code testnum=2
  `----


  Verify that both all quiz and code portions are correct via
  ,----
  | make test
  `----

  before using
  ,----
  | make zip
  `----

  to create a zip to submit.

4 Submission

Follow the instructions at the end of Lab01 if you need a refresher on how to upload your completed lab zip to Gradescope.


Author: Chris Kauffman (profk@umd.edu)
Date: 2024-09-30 Mon 10:21