# Debugging with lldb - part 1

## Abstract
*In the previous article ([MachO Binary Analysis with objdump](https://blog.reveng3.org/macho-binary-analysis-with-objdump)), we have followed step-by-step the compilation of an Objective C program. We have seen all the steps that lead from the code to the Assembly. Now it's time to see what happens at the assembly level.*

*We will use LLDB, the XCode debugger. It's gonna be a challenge for me as well, for I am more versed in GDB.*

# Debugging with LLDB

Previously we used a 'dry' version of the 'myNumber' program - I just added some printouts in the code to simplify the comprehension of the assembly code. 

We will work with the following program:

```
//
//  main.m
//  DebugMe
//
//  Created by Gabriel Biondo on 24/03/2022.
//

#import <Foundation/Foundation.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define STRING_FORMAT       @"%@"
#define START_MSG           @"INITIALISING RANDOMNESS"
#define GENERATE            @"GENERATING RANDOM NUMBER"
#define MAXIMUM             123


@interface myNumber: NSObject

@property int value;

- (Boolean) isPerfectSquare;
- (int) nearestPerfectSquare;
- (Boolean) isPrime;
- (void) randomInit;

@end

@implementation myNumber

- (void) randomInit {
    NSLog(STRING_FORMAT, START_MSG);
    srand(time(0));
    NSLog(STRING_FORMAT, GENERATE);
    int num = rand() % MAXIMUM;
    NSLog(@"Generated number: %i", num);
    self.value = num;
}

- (Boolean) isPerfectSquare{
    NSLog(@"Checking perfect square");
    double num = (double)self.value;
    double sqr = sqrt(num);
    int squareRoot = (int) sqr;
    return (squareRoot*squareRoot == self.value);
}

- (int) nearestPerfectSquare {
    NSLog(@"Looking for perfect squares");
    int nearest = 0;
    if ([self isPerfectSquare]) {
        nearest = self.value;
    } else {
        double num = (double)self.value;
        double sqr = sqrt(num);
        int low = (int) sqr;
        int hi = low + 1;
        int lowq = low * low;
        int hiq = hi * hi;
        int deltaLow = self.value - lowq;
        int deltaHi = hiq - self.value;
        if (deltaLow < deltaHi) {
            NSLog(@"The nearest square is the lowest one");
            nearest = lowq;
        }
        if (deltaHi < deltaLow) {
            NSLog(@"The nearest square is the highest one");
            nearest = hiq;
        }
        
        if (deltaHi == deltaLow){
            NSLog(@"The given number is exactly in the middle of two perfect squares: %i and %i. Returning the lowest", lowq,hiq);
            nearest = lowq;
        }
    }
    NSLog(@"Returning the value");
    return nearest;
}

- (Boolean) isPrime{
    NSLog(@"Checking primality");
    Boolean result = TRUE;
    if (self.value > 2){
        double num = (double)self.value;
        double sqr = sqrt(num);
        int threshold = 1 + (int) sqr;
        for (int i=2; i<=threshold; i++){
            if ((self.value % i) == 0) {
                result = FALSE;
            }
        }
    } else {
        result = FALSE;
    }
    return result;
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        myNumber * m = [myNumber new];
        myNumber * n = [myNumber new];
        myNumber * o = [[myNumber alloc] init];
        myNumber * p = [[myNumber alloc] init];
        myNumber * q = [[myNumber alloc] init];
        n.value = 144;
        m.value = 155;
        o.value = 20;
        p.value = 73;
        
        if ([n isPerfectSquare]) {
            NSLog(@"%i is a perfect square", n.value);
        } else {
            NSLog(@"%i is not a perfect square", n.value);
        }

        if ([m isPerfectSquare]) {
            NSLog(@"%i is a perfect square", m.value);
        } else {
            NSLog(@"%i is not a perfect square", m.value);
        }
        
        int k = [m nearestPerfectSquare];
        NSLog(@"The nearest square to %i is %i", m.value, k);
        int h = [n nearestPerfectSquare];
        NSLog(@"The nearest square to %i is %i", n.value, h);
        int j = [o nearestPerfectSquare];
        NSLog(@"The nearest square to %i is %i", o.value, j);
        int i = [p nearestPerfectSquare];
        NSLog(@"The nearest square to %i is %i", p.value, i);
        
        if ([p isPrime]) {
            NSLog(@"%i is prime", p.value);
        } else {
            NSLog(@"%i is not prime", p.value);
        }
        
        if ([m isPrime]) {
            NSLog(@"%i is prime", m.value);
        } else {
            NSLog(@"%i is not prime", m.value);
        }
        
        [q randomInit];
    }
    return 0;
}
```

Typical output of this program is as follows:

```
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Checking perfect square
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] 144 is a perfect square
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Checking perfect square
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] 155 is not a perfect square
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Looking for perfect squares
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Checking perfect square
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] The nearest square is the lowest one
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Returning the value
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] The nearest square to 155 is 144
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Looking for perfect squares
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Checking perfect square
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Returning the value
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] The nearest square to 144 is 144
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Looking for perfect squares
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Checking perfect square
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] The nearest square is the lowest one
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Returning the value
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] The nearest square to 20 is 16
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Looking for perfect squares
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Checking perfect square
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] The nearest square is the highest one
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Returning the value
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] The nearest square to 73 is 81
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] Checking primality
2022-03-30 10:40:42.775 myNumberExtended[97845:5242525] 73 is prime
2022-03-30 10:40:42.776 myNumberExtended[97845:5242525] Checking primality
2022-03-30 10:40:42.776 myNumberExtended[97845:5242525] 155 is not prime
2022-03-30 10:40:42.776 myNumberExtended[97845:5242525] INITIALISING RANDOMNESS
2022-03-30 10:40:42.776 myNumberExtended[97845:5242525] GENERATING RANDOM NUMBER
2022-03-30 10:40:42.776 myNumberExtended[97845:5242525] Generated number: 58
```
We attach ```lldb``` to a program simply by launching ```lldb myNumberExtended```. Easy as π. 

## Working with breakpoints

The very first thing I used to do in GDB was to set a breakpoint for the ```main``` routine - if I emulate this here, I obtain: 

```
(lldb) target create "myNumberExtended"
Current executable set to '/Users/gbiondo/EXP312/Debugging/myNumberExtended' (x86_64).
(lldb) breakpoint set -name main
Breakpoint 1: 10 locations.
(lldb) breakpoint list 
Current breakpoints:
1: name = 'main', locations = 10
  1.1: where = myNumberExtended`main, address = myNumberExtended[0x00000001000039f0], unresolved, hit count = 0 
  1.2: where = Foundation`-[NSBlockOperation main], address = Foundation[0x00007ff801229338], unresolved, hit count = 0 
  1.3: where = Foundation`-[NSThread main], address = Foundation[0x00007ff8012403c5], unresolved, hit count = 0 
  1.4: where = Foundation`-[NSFilesystemItemRemoveOperation main], address = Foundation[0x00007ff801240eef], unresolved, hit count = 0 
  1.5: where = Foundation`-[NSInvocationOperation main], address = Foundation[0x00007ff80125580b], unresolved, hit count = 0 
  1.6: where = Foundation`-[NSOperation main], address = Foundation[0x00007ff801256098], unresolved, hit count = 0 
  1.7: where = Foundation`-[NSFilesystemItemMoveOperation main], address = Foundation[0x00007ff8012955b7], unresolved, hit count = 0 
  1.8: where = Foundation`-[NSDirectoryTraversalOperation main], address = Foundation[0x00007ff8012d9492], unresolved, hit count = 0 
  1.9: where = Foundation`-[_NSBarrierOperation main], address = Foundation[0x00007ff8013a6e9c], unresolved, hit count = 0 
  1.10: where = Security`Security::OSXCode::main(), address = Security[0x00007ff802617780], unresolved, hit count = 0 
```

Ten different locations for a breakpoint are not what I want. Let's delete them and find a better approach. Here it seems there's no "dot notation", but "tick notation", hence I proceed as follows:

```
(lldb) breakpoint delete 
About to delete all breakpoints, do you want to do that?: [Y/n] 
All breakpoints removed. (1 breakpoint)
(lldb) breakpoint set myNumberExtended`main
error: invalid combination of options for the given command
```

This looks odd, at a first glance: if i use the breakpoint command, I receive an error. I googled a little bit to find the solution - here one needs to use the ```_regexp-break``` command:

``` 
(lldb) help _regexp-break
Set a breakpoint using one of several shorthand formats.  Expects 'raw' input (see 'help raw-input'.)

Syntax: 
_regexp-break <filename>:<linenum>:<colnum>
              main.c:12:21          // Break at line 12 and column 21 of main.c

_regexp-break <filename>:<linenum>
              main.c:12             // Break at line 12 of main.c

_regexp-break <linenum>
              12                    // Break at line 12 of current file

_regexp-break 0x<address>
              0x1234000             // Break at address 0x1234000

_regexp-break <name>
              main                  // Break in 'main' after the prologue

_regexp-break &<name>
              &main                 // Break at first instruction in 'main'

_regexp-break <module>`<name>
              libc.so`malloc        // Break in 'malloc' from 'libc.so'

_regexp-break /<source-regex>/
              /break here/          // Break on source lines in current file
                                    // containing text 'break here'.
```

The command is shortened with the letter ```b```. Now we can do:

```
(lldb) b myNumberExtended`main
Breakpoint 2: where = myNumberExtended`main, address = 0x00000001000039f0
```

So far, so good. Let's execute it and see what happens:

```
(lldb) r
Process 69433 launched: '/Users/gbiondo/EXP312/Debugging/myNumberExtended' (x86_64)
Process 69433 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
    frame #0: 0x00000001000039f0 myNumberExtended`main
myNumberExtended`main:
->  0x1000039f0 <+0>: push   rbp
    0x1000039f1 <+1>: mov    rbp, rsp
    0x1000039f4 <+4>: sub    rsp, 0x50
    0x1000039f8 <+8>: mov    dword ptr [rbp - 0x4], 0x0
Target 0: (myNumberExtended) stopped.
```

The breakpoint has been hit. Now it would be good to set breakpoints for other subroutines. I recently discovered this page ([GDB to LLDB command map](https://lldb.llvm.org/use/map.html)) that maps GDB commands to LLDB - saving me big headaches. There i find this shortcut:

```
This one finds debug symbols:
(lldb) image lookup -r -n <FUNC_REGEX>

This one finds non-debug symbols:
(lldb) image lookup -r -s <FUNC_REGEX> 
```
so I work as follows:
```
(lldb) image lookup -r -n randomInit
1 match found in /Users/gbiondo/EXP312/Debugging/myNumberExtended:
        Address: myNumberExtended[0x0000000100003680] (myNumberExtended.__TEXT.__text + 0)
        Summary: myNumberExtended`-[myNumber randomInit]
(lldb) image lookup -r -n isPerfectSquare
1 match found in /Users/gbiondo/EXP312/Debugging/myNumberExtended:
        Address: myNumberExtended[0x0000000100003710] (myNumberExtended.__TEXT.__text + 144)
        Summary: myNumberExtended`-[myNumber isPerfectSquare]
(lldb) image lookup -r -n nearestPerfectSquare
1 match found in /Users/gbiondo/EXP312/Debugging/myNumberExtended:
        Address: myNumberExtended[0x00000001000037a0] (myNumberExtended.__TEXT.__text + 288)
        Summary: myNumberExtended`-[myNumber nearestPerfectSquare]
(lldb) image lookup -r -n isPrime
1 match found in /Users/gbiondo/EXP312/Debugging/myNumberExtended:
        Address: myNumberExtended[0x00000001000038e0] (myNumberExtended.__TEXT.__text + 608)
        Summary: myNumberExtended`-[myNumber isPrime]
```

Obviously I can add a breakpoint for ```isPrime``` as done before:

```
(lldb) b myNumberExtended`-[myNumber isPrime]
Breakpoint 3: where = myNumberExtended`-[myNumber isPrime], address = 0x00000001000038e0
```

or i can set a breakpoint at a memory address (here I do it for ```randomInit```):

```
(lldb) breakpoint set -a 0x0000000100003680
Breakpoint 4: where = myNumberExtended`-[myNumber randomInit], address = 0x0000000100003680
```

choose your bane and go ahead with all remaining subroutines. At the end of the process you will end up with something like:

```
(lldb) breakpoint list 
Current breakpoints:
2: name = 'main', module = myNumberExtended, locations = 1, resolved = 1, hit count = 1
  2.1: where = myNumberExtended`main, address = 0x00000001000039f0, resolved, hit count = 1 

3: name = '-[myNumber isPrime]', module = myNumberExtended, locations = 1
  3.1: where = myNumberExtended`-[myNumber isPrime], address = 0x00000001000038e0, unresolved, hit count = 0 

4: address = myNumberExtended[0x0000000100003680], locations = 1
  4.1: where = myNumberExtended`-[myNumber randomInit], address = 0x0000000100003680, unresolved, hit count = 0 

5: name = '-[myNumber isPerfectSquare]', module = myNumberExtended, locations = 1
  5.1: where = myNumberExtended`-[myNumber isPerfectSquare], address = 0x0000000100003710, unresolved, hit count = 0 

6: name = '-[myNumber nearestPerfectSquare]', module = myNumberExtended, locations = 1
  6.1: where = myNumberExtended`-[myNumber nearestPerfectSquare], address = 0x00000001000037a0, unresolved, hit count = 0 
```
Note that the first execution of the program changed the status of the first breakpoint from ```unresolved``` to ```resolved```, and the hit count has been incremented to ```1```.

If we run the program now, it will stop at each subroutine. To continue just type ```c``` and hit return (or just hit return, if you already typed ```c```-return once. The key return hit alone repeats the last command). You will see something like:

```
(lldb) r
Process 72978 launched: '/Users/gbiondo/EXP312/Debugging/myNumberExtended' (x86_64)
Process 72978 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
    frame #0: 0x00000001000039f0 myNumberExtended`main
myNumberExtended`main:
->  0x1000039f0 <+0>: push   rbp
    0x1000039f1 <+1>: mov    rbp, rsp
    0x1000039f4 <+4>: sub    rsp, 0x50
    0x1000039f8 <+8>: mov    dword ptr [rbp - 0x4], 0x0
Target 0: (myNumberExtended) stopped.

(lldb) c
Process 72978 resuming
Process 72978 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 5.1
    frame #0: 0x0000000100003710 myNumberExtended`-[myNumber isPerfectSquare]
myNumberExtended`-[myNumber isPerfectSquare]:
->  0x100003710 <+0>: push   rbp
    0x100003711 <+1>: mov    rbp, rsp
    0x100003714 <+4>: sub    rsp, 0x30
    0x100003718 <+8>: mov    rax, rdi
Target 0: (myNumberExtended) stopped.

(lldb) c
Process 72978 resuming
2022-03-29 13:57:12.271864+0100 myNumberExtended[72978:4841122] Checking perfect square
2022-03-29 13:57:12.272346+0100 myNumberExtended[72978:4841122] 144 is a perfect square
Process 72978 stopped
```
I added some spaces to help reading the output, obtaining three blocks. The control flow enters the first block when invoking ```main```, and when the ```isPerfectSquare``` routine gets invoked, the control flow passes to the second block. Once we hit ```c```, the output is presented, the routine exits, and the control flow returns to ```main```.

Here's the list of breakpoints of the program:

```
(lldb) breakpoint list 
Current breakpoints:
2: name = 'main', module = myNumberExtended, locations = 1, resolved = 1, hit count = 2
  2.1: where = myNumberExtended`main, address = 0x00000001000039f0, resolved, hit count = 2 

3: name = '-[myNumber isPrime]', module = myNumberExtended, locations = 1, resolved = 1, hit count = 2
  3.1: where = myNumberExtended`-[myNumber isPrime], address = 0x00000001000038e0, resolved, hit count = 2 

4: address = myNumberExtended[0x0000000100003680], locations = 1, resolved = 1, hit count = 1
  4.1: where = myNumberExtended`-[myNumber randomInit], address = 0x0000000100003680, resolved, hit count = 1 

5: name = '-[myNumber isPerfectSquare]', module = myNumberExtended, locations = 1, resolved = 1, hit count = 6
  5.1: where = myNumberExtended`-[myNumber isPerfectSquare], address = 0x0000000100003710, resolved, hit count = 6 

6: name = '-[myNumber nearestPerfectSquare]', module = myNumberExtended, locations = 1, resolved = 1, hit count = 4
  6.1: where = myNumberExtended`-[myNumber nearestPerfectSquare], address = 0x00000001000037a0, resolved, hit count = 4
```

Breakpoint 6 served us well - let's give it some rest:

```
(lldb) breakpoint delete 6
1 breakpoints deleted; 0 breakpoint locations disabled.
```

Far from being the masters of the breakpoints, we now have a fair understanding of how to use them.

## Disassembling

Disassembling the whole program can be quite useless - also disassembling the whole ```main``` routine produces a lot of code. Remember: the final objective of these efforts would be doing reverse engineering, so we want to make our lives easier... and we have to consider the fact that - at least until now - we are **not** able to write any assembly :)!

Let's start by disassembling one routine, for instance ```nearestPerfectSquare```. We proceed as follows:

```
(lldb) disassemble -n nearestPerfectSquare
myNumberExtended`-[myNumber nearestPerfectSquare]:
myNumberExtended[0x100003710] <+0>:   push   rbp
myNumberExtended[0x100003711] <+1>:   mov    rbp, rsp
myNumberExtended[0x100003714] <+4>:   sub    rsp, 0x50
myNumberExtended[0x100003718] <+8>:   mov    rax, rdi
myNumberExtended[0x10000371b] <+11>:  lea    rdi, [rip + 0x98e]        ; @"Looking for perfect squares"
myNumberExtended[0x100003722] <+18>:  mov    qword ptr [rbp - 0x8], rax
myNumberExtended[0x100003726] <+22>:  mov    qword ptr [rbp - 0x10], rsi
myNumberExtended[0x10000372a] <+26>:  mov    al, 0x0
myNumberExtended[0x10000372c] <+28>:  call   0x100003cda               ; symbol stub for: NSLog
myNumberExtended[0x100003731] <+33>:  mov    dword ptr [rbp - 0x14], 0x0
myNumberExtended[0x100003738] <+40>:  mov    rdi, qword ptr [rbp - 0x8]
myNumberExtended[0x10000373c] <+44>:  mov    rsi, qword ptr [rip + 0x4a75] ; "isPerfectSquare"
myNumberExtended[0x100003743] <+51>:  call   qword ptr [rip + 0x8b7]   ; (void *)0x0000000000000000
myNumberExtended[0x100003749] <+57>:  cmp    al, 0x0
myNumberExtended[0x10000374b] <+59>:  je     0x10000376a               ; <+90>
myNumberExtended[0x100003751] <+65>:  mov    rdi, qword ptr [rbp - 0x8]
myNumberExtended[0x100003755] <+69>:  mov    rsi, qword ptr [rip + 0x4a54] ; "value"
myNumberExtended[0x10000375c] <+76>:  call   qword ptr [rip + 0x89e]   ; (void *)0x0000000000000000
myNumberExtended[0x100003762] <+82>:  mov    dword ptr [rbp - 0x14], eax
myNumberExtended[0x100003765] <+85>:  jmp    0x10000385a               ; <+330>
myNumberExtended[0x10000376a] <+90>:  mov    rdi, qword ptr [rbp - 0x8]
myNumberExtended[0x10000376e] <+94>:  mov    rsi, qword ptr [rip + 0x4a3b] ; "value"
myNumberExtended[0x100003775] <+101>: call   qword ptr [rip + 0x885]   ; (void *)0x0000000000000000
myNumberExtended[0x10000377b] <+107>: cvtsi2sd xmm0, eax
myNumberExtended[0x10000377f] <+111>: movsd  qword ptr [rbp - 0x20], xmm0
myNumberExtended[0x100003784] <+116>: movsd  xmm0, qword ptr [rbp - 0x20] ; xmm0 = mem[0],zero 
myNumberExtended[0x100003789] <+121>: sqrtsd xmm0, xmm0
myNumberExtended[0x10000378d] <+125>: movsd  qword ptr [rbp - 0x28], xmm0
myNumberExtended[0x100003792] <+130>: cvttsd2si eax, qword ptr [rbp - 0x28]
myNumberExtended[0x100003797] <+135>: mov    dword ptr [rbp - 0x2c], eax
myNumberExtended[0x10000379a] <+138>: mov    eax, dword ptr [rbp - 0x2c]
myNumberExtended[0x10000379d] <+141>: add    eax, 0x1
myNumberExtended[0x1000037a0] <+144>: mov    dword ptr [rbp - 0x30], eax
myNumberExtended[0x1000037a3] <+147>: mov    eax, dword ptr [rbp - 0x2c]
myNumberExtended[0x1000037a6] <+150>: imul   eax, dword ptr [rbp - 0x2c]
myNumberExtended[0x1000037aa] <+154>: mov    dword ptr [rbp - 0x34], eax
myNumberExtended[0x1000037ad] <+157>: mov    eax, dword ptr [rbp - 0x30]
myNumberExtended[0x1000037b0] <+160>: imul   eax, dword ptr [rbp - 0x30]
myNumberExtended[0x1000037b4] <+164>: mov    dword ptr [rbp - 0x38], eax
myNumberExtended[0x1000037b7] <+167>: mov    rdi, qword ptr [rbp - 0x8]
myNumberExtended[0x1000037bb] <+171>: mov    rsi, qword ptr [rip + 0x49ee] ; "value"
myNumberExtended[0x1000037c2] <+178>: call   qword ptr [rip + 0x838]   ; (void *)0x0000000000000000
myNumberExtended[0x1000037c8] <+184>: sub    eax, dword ptr [rbp - 0x34]
myNumberExtended[0x1000037cb] <+187>: mov    dword ptr [rbp - 0x3c], eax
myNumberExtended[0x1000037ce] <+190>: mov    eax, dword ptr [rbp - 0x38]
myNumberExtended[0x1000037d1] <+193>: mov    dword ptr [rbp - 0x44], eax
myNumberExtended[0x1000037d4] <+196>: mov    rdi, qword ptr [rbp - 0x8]
myNumberExtended[0x1000037d8] <+200>: mov    rsi, qword ptr [rip + 0x49d1] ; "value"
myNumberExtended[0x1000037df] <+207>: call   qword ptr [rip + 0x81b]   ; (void *)0x0000000000000000
myNumberExtended[0x1000037e5] <+213>: mov    ecx, eax
myNumberExtended[0x1000037e7] <+215>: mov    eax, dword ptr [rbp - 0x44]
myNumberExtended[0x1000037ea] <+218>: sub    eax, ecx
myNumberExtended[0x1000037ec] <+220>: mov    dword ptr [rbp - 0x40], eax
myNumberExtended[0x1000037ef] <+223>: mov    eax, dword ptr [rbp - 0x3c]
myNumberExtended[0x1000037f2] <+226>: cmp    eax, dword ptr [rbp - 0x40]
myNumberExtended[0x1000037f5] <+229>: jge    0x10000380f               ; <+255>
myNumberExtended[0x1000037fb] <+235>: lea    rdi, [rip + 0x8ce]        ; @"The nearest square is the lowest one"
myNumberExtended[0x100003802] <+242>: mov    al, 0x0
myNumberExtended[0x100003804] <+244>: call   0x100003cda               ; symbol stub for: NSLog
myNumberExtended[0x100003809] <+249>: mov    eax, dword ptr [rbp - 0x34]
myNumberExtended[0x10000380c] <+252>: mov    dword ptr [rbp - 0x14], eax
myNumberExtended[0x10000380f] <+255>: mov    eax, dword ptr [rbp - 0x40]
myNumberExtended[0x100003812] <+258>: cmp    eax, dword ptr [rbp - 0x3c]
myNumberExtended[0x100003815] <+261>: jge    0x10000382f               ; <+287>
myNumberExtended[0x10000381b] <+267>: lea    rdi, [rip + 0x8ce]        ; @"The nearest square is the highest one"
myNumberExtended[0x100003822] <+274>: mov    al, 0x0
myNumberExtended[0x100003824] <+276>: call   0x100003cda               ; symbol stub for: NSLog
myNumberExtended[0x100003829] <+281>: mov    eax, dword ptr [rbp - 0x38]
myNumberExtended[0x10000382c] <+284>: mov    dword ptr [rbp - 0x14], eax
myNumberExtended[0x10000382f] <+287>: mov    eax, dword ptr [rbp - 0x40]
myNumberExtended[0x100003832] <+290>: cmp    eax, dword ptr [rbp - 0x3c]
myNumberExtended[0x100003835] <+293>: jne    0x100003855               ; <+325>
myNumberExtended[0x10000383b] <+299>: lea    rdi, [rip + 0x8ce]        ; @"The given number is exactly in the middle of two perfect squares: %i and %i. Returning the lowest"
myNumberExtended[0x100003842] <+306>: mov    esi, dword ptr [rbp - 0x34]
myNumberExtended[0x100003845] <+309>: mov    edx, dword ptr [rbp - 0x38]
myNumberExtended[0x100003848] <+312>: mov    al, 0x0
myNumberExtended[0x10000384a] <+314>: call   0x100003cda               ; symbol stub for: NSLog
myNumberExtended[0x10000384f] <+319>: mov    eax, dword ptr [rbp - 0x34]
myNumberExtended[0x100003852] <+322>: mov    dword ptr [rbp - 0x14], eax
myNumberExtended[0x100003855] <+325>: jmp    0x10000385a               ; <+330>
myNumberExtended[0x10000385a] <+330>: lea    rdi, [rip + 0x8cf]        ; @"Returning the value"
myNumberExtended[0x100003861] <+337>: mov    al, 0x0
myNumberExtended[0x100003863] <+339>: call   0x100003cda               ; symbol stub for: NSLog
myNumberExtended[0x100003868] <+344>: mov    eax, dword ptr [rbp - 0x14]
myNumberExtended[0x10000386b] <+347>: add    rsp, 0x50
myNumberExtended[0x10000386f] <+351>: pop    rbp
myNumberExtended[0x100003870] <+352>: ret    
myNumberExtended[0x100003871] <+353>: nop    word ptr cs:[rax + rax]
myNumberExtended[0x10000387b] <+363>: nop    dword ptr [rax + rax]
```
If we take a look at the Objective-C code, we immediately see that this routine gets the value of the property ```value``` and finds the nearest square to it.

This is interesting because this way we can learn where a return value is stored.

We have two possibilities: 

1. set a breakpoint to the beginning of the routine and see what happens, step by step
1. set a breakpoint somewhere before the end of the routine and see the values of the registers.

Once again, here we assume that we have no talent at all and *we do not know any assembly* - so let's go for the easiest option.

We can set a breakpoint at the address ```0x100003848```, just before the ```NSLog``` instruction is called and examine the registers. From the Objective C code we know that the first object on which the method is invoked has the property ```value``` set to 155 (or ```0x9B```). This value is between 12*12=144 (```0X90```) and 13*13=169 (```0xA9```). The nearest square is obviously 144. 

The situation should be as follows:

```
(lldb) br s -a 0x100003861
Breakpoint 4: where = myNumberExtended`-[myNumber nearestPerfectSquare] + 337, address = 0x0000000100003861
(lldb) br list 
Current breakpoints:
3: address = myNumberExtended[0x0000000100003868], locations = 1 Options: disabled 
  3.1: where = myNumberExtended`-[myNumber nearestPerfectSquare] + 344, address = 0x0000000100003868, unresolved, hit count = 4 

4: address = myNumberExtended[0x0000000100003861], locations = 1
  4.1: where = myNumberExtended`-[myNumber nearestPerfectSquare] + 337, address = 0x0000000100003861, unresolved, hit count = 0 
```

Now if we run the program, the execution will stop once the ```RIP``` (instruction pointer - we'll come back on this later) hits the value 0x0000000100003848. In fact:

```
(lldb) r
Process 4310 launched: '/Users/gbiondo/EXP312/Debugging/myNumberExtended' (x86_64)
2022-03-30 14:05:50.875159+0100 myNumberExtended[4310:5367748] Checking perfect square
2022-03-30 14:05:50.875445+0100 myNumberExtended[4310:5367748] 144 is a perfect square
2022-03-30 14:05:50.875456+0100 myNumberExtended[4310:5367748] Checking perfect square
2022-03-30 14:05:50.875463+0100 myNumberExtended[4310:5367748] 155 is not a perfect square
2022-03-30 14:05:50.875470+0100 myNumberExtended[4310:5367748] Looking for perfect squares
2022-03-30 14:05:50.875477+0100 myNumberExtended[4310:5367748] Checking perfect square
2022-03-30 14:05:50.875483+0100 myNumberExtended[4310:5367748] The nearest square is the lowest one
Process 4310 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1
    frame #0: 0x0000000100003861 myNumberExtended`-[myNumber nearestPerfectSquare] + 337
myNumberExtended`-[myNumber nearestPerfectSquare]:
->  0x100003861 <+337>: mov    al, 0x0
    0x100003863 <+339>: call   0x100003cda               ; symbol stub for: NSLog
    0x100003868 <+344>: mov    eax, dword ptr [rbp - 0x14]
    0x10000386b <+347>: add    rsp, 0x50
Target 0: (myNumberExtended) stopped.
```
We give the command ```n``` (short for ```﻿﻿thread step-over```) twice, reaching the address ```-[myNumber nearestPerfectSquare] + 344``` and obtain:

```
(lldb) n
Process 4310 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x0000000100003863 myNumberExtended`-[myNumber nearestPerfectSquare] + 339
myNumberExtended`-[myNumber nearestPerfectSquare]:
->  0x100003863 <+339>: call   0x100003cda               ; symbol stub for: NSLog
    0x100003868 <+344>: mov    eax, dword ptr [rbp - 0x14]
    0x10000386b <+347>: add    rsp, 0x50
    0x10000386f <+351>: pop    rbp
Target 0: (myNumberExtended) stopped.
(lldb) n
2022-03-30 14:10:34.213710+0100 myNumberExtended[4310:5367748] Returning the value
Process 4310 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x0000000100003868 myNumberExtended`-[myNumber nearestPerfectSquare] + 344
myNumberExtended`-[myNumber nearestPerfectSquare]:
->  0x100003868 <+344>: mov    eax, dword ptr [rbp - 0x14]
    0x10000386b <+347>: add    rsp, 0x50
    0x10000386f <+351>: pop    rbp
    0x100003870 <+352>: ret    
Target 0: (myNumberExtended) stopped.
```
Now it is time to examine the value of registers:
```
(lldb) register read 
General Purpose Registers:
       rax = 0xe62a2c872238004d
       rbx = 0x00000001000c8060
       rcx = 0x000000010080b040
       rdx = 0x0000000000000000
       rdi = 0x000000010080b040
       rsi = 0x000000010080b040
       rbp = 0x00007ff7bfeff860
       rsp = 0x00007ff7bfeff810
        r8 = 0x00007ff7bfeff5c0
        r9 = 0x0000000000000040
       r10 = 0x0000000000000000
       r11 = 0x0000000000000246
       r12 = 0x00000001000903a0  dyld`_NSConcreteStackBlock
       r13 = 0x00007ff7bfeff978
       r14 = 0x0000000100003990  myNumberExtended`main
       r15 = 0x000000010007c010  dyld`dyld4::sConfigBuffer
       rip = 0x0000000100003868  myNumberExtended`-[myNumber nearestPerfectSquare] + 344
    rflags = 0x0000000000000206
        cs = 0x000000000000002b
        fs = 0x0000000000000000
        gs = 0x0000000000000000
```
Observe that ```RIP```, the Instruction Point Register, points to the next instruction to be ran. Remembering that we *know no assembly at all*, we take another step in the debug and see how the values of the registers change:
```
(lldb) s
Process 4310 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into
    frame #0: 0x000000010000386b myNumberExtended`-[myNumber nearestPerfectSquare] + 347
myNumberExtended`-[myNumber nearestPerfectSquare]:
->  0x10000386b <+347>: add    rsp, 0x50
    0x10000386f <+351>: pop    rbp
    0x100003870 <+352>: ret    
    0x100003871 <+353>: nop    word ptr cs:[rax + rax]
Target 0: (myNumberExtended) stopped.
(lldb) register read
General Purpose Registers:
       rax = 0x0000000000000090
       rbx = 0x00000001000c8060
       rcx = 0x000000010080b040
       rdx = 0x0000000000000000
       rdi = 0x000000010080b040
       rsi = 0x000000010080b040
       rbp = 0x00007ff7bfeff860
       rsp = 0x00007ff7bfeff810
        r8 = 0x00007ff7bfeff5c0
        r9 = 0x0000000000000040
       r10 = 0x0000000000000000
       r11 = 0x0000000000000246
       r12 = 0x00000001000903a0  dyld`_NSConcreteStackBlock
       r13 = 0x00007ff7bfeff978
       r14 = 0x0000000100003990  myNumberExtended`main
       r15 = 0x000000010007c010  dyld`dyld4::sConfigBuffer
       rip = 0x000000010000386b  myNumberExtended`-[myNumber nearestPerfectSquare] + 347
    rflags = 0x0000000000000206
        cs = 0x000000000000002b
        fs = 0x0000000000000000
        gs = 0x0000000000000000
```
We observe that the only two registers that have changed are ```RAX``` and obviously ```RIP```.  Furthermore, ```RAX```  contains exactly the value we are looking for (0x90) - we can conjecture that this register will contain the return value for the subroutine. If this is true, we may want to change it in a way that contains a number we decide - let's say ```0x1723```, or ```5923```.

To do so, it would suffice to launch the command:
```
(lldb) register write rax 0x1723
(lldb) register read rax 
     rax = 0x0000000000001723
```
and see the printout in the main program.

We hit ```n``` a couple of times to return to the main program (the ```ret``` instruction):

```
(lldb) s
Process 4310 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into
    frame #0: 0x000000010000386f myNumberExtended`-[myNumber nearestPerfectSquare] + 351
myNumberExtended`-[myNumber nearestPerfectSquare]:
->  0x10000386f <+351>: pop    rbp
    0x100003870 <+352>: ret    
    0x100003871 <+353>: nop    word ptr cs:[rax + rax]
    0x10000387b <+363>: nop    dword ptr [rax + rax]
Target 0: (myNumberExtended) stopped.
(lldb) n
Process 4310 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x0000000100003870 myNumberExtended`-[myNumber nearestPerfectSquare] + 352
myNumberExtended`-[myNumber nearestPerfectSquare]:
->  0x100003870 <+352>: ret    
    0x100003871 <+353>: nop    word ptr cs:[rax + rax]
    0x10000387b <+363>: nop    dword ptr [rax + rax]

myNumberExtended`-[myNumber isPrime]:
    0x100003880 <+0>:   push   rbp
Target 0: (myNumberExtended) stopped.

(lldb) s
* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x0000000100003b28 myNumberExtended`main + 408
myNumberExtended`main:
->  0x100003b28 <+408>: mov    dword ptr [rbp - 0x3c], eax
    0x100003b2b <+411>: mov    rdi, qword ptr [rbp - 0x18]
    0x100003b2f <+415>: mov    rsi, qword ptr [rip + 0x467a] ; "value"
    0x100003b36 <+422>: call   qword ptr [rip + 0x4c4]   ; (void *)0x00007ff812cde040: objc_msgSend
Target 0: (myNumberExtended) stopped.
(lldb) register read 
General Purpose Registers:
       rax = 0x0000000000001723
       rbx = 0x00000001000c8060
       rcx = 0x000000010080b040
       rdx = 0x0000000000000000
       rdi = 0x000000010080b040
       rsi = 0x000000010080b040
       rbp = 0x00007ff7bfeff8c0
       rsp = 0x00007ff7bfeff870
        r8 = 0x00007ff7bfeff5c0
        r9 = 0x0000000000000040
       r10 = 0x0000000000000000
       r11 = 0x0000000000000246
       r12 = 0x00000001000903a0  dyld`_NSConcreteStackBlock
       r13 = 0x00007ff7bfeff978
       r14 = 0x0000000100003990  myNumberExtended`main
       r15 = 0x000000010007c010  dyld`dyld4::sConfigBuffer
       rip = 0x0000000100003b28  myNumberExtended`main + 408
    rflags = 0x0000000000000206
        cs = 0x000000000000002b
        fs = 0x0000000000000000
        gs = 0x0000000000000000
```
Hitting a few times ```n``` until we reach ```myNumberExtended`main + 442```, and then hitting it again, we obtain:
```
2022-03-30 14:31:40.787665+0100 myNumberExtended[4310:5367748] The nearest square to 155 is 5923
Process 4310 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x0000000100003b4f myNumberExtended`main + 447
myNumberExtended`main:
->  0x100003b4f <+447>: mov    rdi, qword ptr [rbp - 0x20]
    0x100003b53 <+451>: mov    rsi, qword ptr [rip + 0x4666] ; "nearestPerfectSquare"
    0x100003b5a <+458>: call   qword ptr [rip + 0x4a0]   ; (void *)0x00007ff812cde040: objc_msgSend
    0x100003b60 <+464>: mov    dword ptr [rbp - 0x40], eax
Target 0: (myNumberExtended) stopped.
```
So, our conjecture was right.

# Conclusions
This is a very long article. The idea behind it is to show how ```lldb``` can be used, and to ignite some itch for assembly programming.
I will come back on these kind of exercises - I find them quite funny :) 
'til next time...
