# Section 2

In this section we’re going to have fun.

Update your section repository, cd s02, and make. This will built a number of fun programs.

## Setup

Let’s run one:

$./fun01 😿😿😿😿😿😿😿😿 no fun 😿😿😿😿😿😿😿😿  That wasn’t fun! These programs are puzzles. Look at fundriver.cc and you’ll see the ground rules. The driver’s main function first creates a single C string that contains all program arguments, separated by spaces. It then calls the fun function, passing in that string. The fun function returns an integer; if fun(str) returns 0, then the driver has fun, and if it returns anything else, no fun is had (the function boo() is called, which prints the no fun message). We want to have fun, how can we have fun? Well might as well look to see what the function is doing! (Open fun01.cc) Looks like this fun function will return 0 if and only if the arguments contain an exclamation point. Let’s test that: $ ./fun01 !
🎉🎉🎉🎉🎊🎊🎊🎊🌽🌽🌽🎊🎊🎊🎊🎉🎉🎉🎉
FUN
🎉🎉🎉🎉🎊🎊🎊🎊🌽🌽🌽🎊🎊🎊🎊🎉🎉🎉🎉
$./fun01 'yay!' 🎉🎉🎉🎉🎊🎊🎊🎊🌽🌽🌽🎊🎊🎊🎊🎉🎉🎉🎉 FUN 🎉🎉🎉🎉🎊🎊🎊🎊🌽🌽🌽🎊🎊🎊🎊🎉🎉🎉🎉$ ./fun01 'amazing!!!!!!!!!!!!!!!!!'
🎉🎉🎉🎉🎊🎊🎊🎊🌽🌽🌽🎊🎊🎊🎊🎉🎉🎉🎉
FUN
🎉🎉🎉🎉🎊🎊🎊🎊🌽🌽🌽🎊🎊🎊🎊🎉🎉🎉🎉
$./fun01 'amazing?' 😿😿😿😿😿😿😿😿 no fun 😿😿😿😿😿😿😿😿  It works. ## GDB Now let’s say that the idea of not having fun is so painful to you that you will do literally anything to avoid it. Is there any way that you could, for example, prevent the boo() function from running? That you could stop the program if it reached boo()? This calls for a debugger breakpoint. A debugger is a program that manages the execution of another program. It lets you run a program, stop it, and examine variables, registers, and the contents of memory. Among the most powerful debugger features is the ability to stop a program if it ever reaches an instruction. This is called “setting a breakpoint”: the breakpoint marks a location that, when reached, “breaks” the program and returns control to the debugger. How would you stop the program from executing boo? $ gdb fun01
(gdb) b boo


Now if we run the program with non-fun arguments

(gdb) r


we will stop before printing “no fun”!

If you’re not careful, though, it’s possible to accidentally step through and print the message. You can do this one step at a time (demo r, followed by several ses); or you can do it by continuing the program by accident (demo r followed by c).

What if you wanted to make this kind of accident wicked unlikely? Well, you could set more breakpoints!

(gdb) b foo
(gdb) r
Breakpoint 1, main (argc=1, argv=0x7fffffffdf88) at fundriver.cc:34
34          boo();
(gdb) x/20i $pc => 0x400c47 <main(int, char**)+375>: lea 0x344(%rip),%rsi # 0x400f92 0x400c4e <main(int, char**)+382>: lea 0x20156b(%rip),%rdi # 0x6021c0 <_ZSt4cerr@@GLIBCXX_3.4> 0x400c55 <main(int, char**)+389>: callq 0x400a70 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> 0x400c5a <main(int, char**)+394>: mov$0x1,%edi
0x400c5f <main(int, char**)+399>:  callq  0x400a90 <exit@plt>


We’ve stopped at the first instruction in the boo function (which has actually been inlined into main, but never mind). But can also set more breakpoints! For example, at the second instruction and the third:

(gdb) b *0x400c4e
(gdb) b *0x400c55


(demo)

But what if you forgot these breakpoints??? Well, that’s a good case for .gdbinit.

## GDB usage

• x for examining memory
• x/20i $pc for examining instructions • autodisplay instructions: display/20i$pc
• -tui
• info registers
• s vs. n

## More fun

Now let’s work through a couple more funs. We’ll try to understand the operation of the funs using GDB and assembly, though for the first 6 funs, the C++ is there if you get stuck.

ASSEMBLY IS HARD. And trying to understand assembly from first principles, without running it, is really hard! As with many aspects of systems, you will have more luck with an approach motivated by experimental science. Try and guess at an input that will work, using cues from the assembly. Develop a hypothesis and test it. For the bomb, you don’t need to fully understand the assembly, you just need to find an input that passes each phase. (That said, you will often end up understanding the assembly—but only after completing the phase with the help of experiments.)

It is also often effective to alternate between working top down, starting from the entry to a function, and bottom up, starting at the return statement. Working from the bottom up, you can eliminate error paths and trace through how the desired result is calculated. Working from the top down, you can develop hypothesis about how the input should look. As long as you have breakpoints set, you can experiment with a free and easy heart. (And if the bomb goes off, who really cares?)

## Fun cheatsheet

• fun02: Calls strtol. Hypothesis: string should be an integer! Adds 1 to the return from strtol. Answer: -1

• fun03: Checks first character of string, then returns second. Answer: any single-character string. Introduces control flow.

• fun04: Any two-character string with both characters same. More control flow.

• fun05: Any nonzero-character string with all characters same. A loop.

• fun06: Any string with length a multiple of 4. For loop.

• fun07: Checks for primes. Work top-down: expects an integer. Test a bunch of integers at command line. Ask students to spot the pattern.

• fun08: Reads three integers, returns a + b - c. Examples: 1 1 2, 0 0 0.

• fun09: Expects a filename of an openable file. Pretty simple.

• fun10: A power of 2 greater than 128. Bitwise arithmetic.

• fun11: A six-or-more character string consisting of uppercase letters.

• fun12: A five-or-more character palindrome.

## Other stuff

The section cheatsheet has a bunch of material on assembly that can be used for reference or presentation if the above doesn’t work for you.