forked from open-education-hub/hardware-software-interface
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
memory-layout/memory-operations-and-GDB: Add reading and tasks
Add reading and tasks for lab 2 and modify config.yaml to render the new content. Signed-off-by: Adrian-George Dumitrache <[email protected]>
- Loading branch information
1 parent
cc014bf
commit 25f4c47
Showing
54 changed files
with
1,533 additions
and
0 deletions.
There are no files selected for viewing
33 changes: 33 additions & 0 deletions
33
chapters/memory-layout/introduction-to-GDB/drills/tasks/inspect/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Data Inspection | ||
|
||
You will solve the exercise starting from the `inspect.c` file located in the `drills/tasks/inspect/support` directory. | ||
|
||
Given the following declarations: | ||
|
||
```c | ||
#include <stdio.h> | ||
|
||
int main() { | ||
unsigned int a = 4127; | ||
int b = -27714; | ||
short c = 1475; | ||
int v[] = {0xCAFEBABE, 0xDEADBEEF, 0x0B00B135, 0xBAADF00D, 0xDEADC0DE}; | ||
|
||
unsigned int *int_ptr = (unsigned int *) &v; | ||
|
||
for (int i = 0 ; i < sizeof(v) / sizeof(*int_ptr) ; ++i) { | ||
++int_ptr; | ||
} | ||
|
||
return 0; | ||
} | ||
``` | ||
|
||
Compile the source code and run the executable with GDB. | ||
Set a breakpoint at `main` and observe how the data is represented in memory. | ||
For this task, you will use the `print` and `examine` commands. | ||
|
||
> **NOTE:** | ||
> | ||
> - To display the value of a variable in hexadecimal, use `p/x variable_name` | ||
> - To display the value from a pointer, use `p *pointer_name`, and to inspect the data at a memory address, use `x memory_address`. |
1 change: 1 addition & 0 deletions
1
chapters/memory-layout/introduction-to-GDB/drills/tasks/inspect/support/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/inspect |
22 changes: 22 additions & 0 deletions
22
chapters/memory-layout/introduction-to-GDB/drills/tasks/inspect/support/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
CC = gcc | ||
CFLAGS = -Wall -g | ||
LDFLAGS = | ||
|
||
TARGET_EXEC = inspect | ||
|
||
SRCS := $(shell find $(SRC_DIRS) -name "*.c") | ||
OBJS := $(SRCS:.c=.o) | ||
|
||
$(info OBJS is $(OBJS)) | ||
$(info SRCS is $(SRCS)) | ||
|
||
$(TARGET_EXEC): $(OBJS) | ||
$(CC) $(OBJS) -o $@ $(LDFLAGS) | ||
|
||
.o: %.c | ||
$(CC) $(CFLAGS) $(LDFLAGS) -c $< -o $@ | ||
|
||
.PHONY: clean | ||
|
||
clean: | ||
$(RM) -r *.o $(TARGET_EXEC) |
22 changes: 22 additions & 0 deletions
22
chapters/memory-layout/introduction-to-GDB/drills/tasks/inspect/support/inspect.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
#include <stdio.h> | ||
|
||
int main(void) | ||
{ | ||
unsigned int a = 4127; | ||
int b = -27714; | ||
short c = 1475; | ||
int v[] = {0xCAFEBABE, 0xDEADBEEF, 0x0B00B135, 0xBAADF00D, 0xDEADC0DE}; | ||
|
||
unsigned int *int_ptr = (unsigned int *) &v; | ||
|
||
for (unsigned int i = 0 ; i < sizeof(v) / sizeof(*int_ptr) ; ++i) | ||
++int_ptr; | ||
|
||
(void) a; | ||
(void) b; | ||
(void) c; | ||
|
||
return 0; | ||
} |
44 changes: 44 additions & 0 deletions
44
chapters/memory-layout/introduction-to-GDB/guides/segfault/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# GDB Tutorial: Debugging a Segfault | ||
|
||
You will solve the exercise starting from the `segfault.c` file located in the `drills/tasks/segfault/support` directory. | ||
|
||
Compile and run the source code from the skeleton (if you are not using the Makefile, make sure to compile with the -g flag). | ||
In short, the program takes a number n, allocates a vector of size n, and initializes it with the first n numbers from the Fibonacci sequence. | ||
However, after running the program, you see: Segmentation fault (core dumped). | ||
|
||
Start GDB with the executable: | ||
|
||
```bash | ||
gdb ./segfault | ||
``` | ||
|
||
Once you have started GDB, all interaction happens through the GDB prompt. | ||
Run the program using the `run` command. | ||
What do you notice? | ||
GDB hangs at the input reads. | ||
|
||
Set a breakpoint at `main` using the `break main` command. | ||
You will see the message in the prompt: | ||
|
||
```c | ||
Breakpoint 1 at 0x7d3: file seg.c, line 21 /* The memory address should not be the same */ | ||
``` | ||
|
||
Next, we will step through the instructions one by one. | ||
To do this, use the `next` or `n` command (watch the GDB cursor to see the current instruction and repeat the process). | ||
You will notice that GDB hangs at `scanf`, so input a value for `n` and continue stepping through. | ||
If you have entered a large value for `n` and want to skip the iteration, use the `continue` command. | ||
Eventually, you will reach the line `v[423433] = 3;`, and GDB will display: | ||
|
||
```bash | ||
Program received signal SIGSEGV, Segmentation fault | ||
``` | ||
|
||
Inspect the memory at `v[423433]` using `x &v[423433]` and you will receive the message: | ||
|
||
```c | ||
Cannot access memory at address 0x5555558f3e94 /* The memory address should not be the same */ | ||
``` | ||
|
||
What happened? | ||
We accessed a memory area with restricted access. |
1 change: 1 addition & 0 deletions
1
chapters/memory-layout/introduction-to-GDB/guides/segfault/support/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/segfault |
22 changes: 22 additions & 0 deletions
22
chapters/memory-layout/introduction-to-GDB/guides/segfault/support/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
CC = gcc | ||
CFLAGS = -Wall -g | ||
LDFLAGS = | ||
|
||
TARGET_EXEC = segfault | ||
|
||
SRCS := $(shell find $(SRC_DIRS) -name "*.c") | ||
OBJS := $(SRCS:.c=.o) | ||
|
||
$(info OBJS is $(OBJS)) | ||
$(info SRCS is $(SRCS)) | ||
|
||
$(TARGET_EXEC): $(OBJS) | ||
$(CC) $(OBJS) -o $@ $(LDFLAGS) | ||
|
||
.o: %.c | ||
$(CC) $(CFLAGS) $(LDFLAGS) -c $< -o $@ | ||
|
||
.PHONY: clean | ||
|
||
clean: | ||
$(RM) -r *.o $(TARGET_EXEC) |
36 changes: 36 additions & 0 deletions
36
chapters/memory-layout/introduction-to-GDB/guides/segfault/support/segfault.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
int nth_fibo(const int n) | ||
{ | ||
if (n == 1 || n == 2) | ||
return 1; | ||
|
||
int first = 1, second = 1, nth_fib = 0; | ||
|
||
for (int i = 3 ; i <= n ; ++i) { | ||
nth_fib = first + second; | ||
first = second; | ||
second = nth_fib; | ||
} | ||
|
||
return nth_fib; | ||
} | ||
|
||
int main(void) | ||
{ | ||
int n; | ||
|
||
scanf("%d", &n); | ||
int *v = malloc(n * sizeof(*v)); | ||
|
||
for (int i = 0 ; i < n; ++i) | ||
v[i] = nth_fibo(i); | ||
|
||
v[423433] = 3; | ||
free(v); | ||
|
||
return 0; | ||
} |
84 changes: 84 additions & 0 deletions
84
chapters/memory-layout/introduction-to-GDB/reading/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# GNU Debugger (GDB) | ||
|
||
## Starting GDB | ||
|
||
GDB is a powerful tool for debugging programs. | ||
It allows you to inspect the state of a program at a certain point in its execution, set breakpoints, and step through the code, among other things. | ||
To start GDB, you need to run the following command: | ||
|
||
```bash | ||
gdb [program_name] | ||
``` | ||
|
||
## Running the Program | ||
|
||
To run the program being debugged, there are two available commands: | ||
|
||
- `r` or `run` - this command will run the program | ||
- `start` - unlike `run`, this command will start the program but immediately stop after entering `main` | ||
|
||
## Breakpoints | ||
|
||
The essential element of GDB is the breakpoint. | ||
Essentially, setting a breakpoint at a certain instruction causes the program's execution to halt every time it reaches that point. | ||
Setting a breakpoint is done with the following command: | ||
|
||
```gdb | ||
break [location] | ||
``` | ||
|
||
where *location* can represent the name of a function, the line number of the code, or even a memory address, in which case the address must be preceded by the symbol *. | ||
For example: `break \*0xCAFEBABE` | ||
|
||
## Stepping through instructions | ||
|
||
- `si` or `stepi` - executes the current instruction | ||
- `ni` or `nexti` - similar to `stepi`, but if the current instruction is a function call, the debugger will not enter the function | ||
- `c` or `continue` - continues program execution until the next breakpoint or until it finishes | ||
- `finish` - continues program execution until leaving the current function | ||
|
||
## Inspecting Memory | ||
|
||
- `p` or `print` var - displays the value of `var`. | ||
Print is a very flexible command, allowing dereferencing of pointers, displaying addresses of variables, and indexing through arrays using *, & and []. | ||
The print command can be followed by the /f parameter specifying the display format (x for hex, d for decimal, s for string). | ||
- `x` or `examine` - Inspects the content at the given address. | ||
The usage of this command is as follows: | ||
|
||
```text | ||
x/nfu address | ||
``` | ||
|
||
where: | ||
|
||
- n is the number of displayed elements | ||
- f is the display format (x for hex, d for decimal, s for string, and i for instructions) | ||
- u is the size of each element (b for 1 byte, h for 2, w for 4, and g for 8 bytes) | ||
|
||
We recommend the article [Debugging](https://ocw.cs.pub.ro/courses/programare/tutoriale/debugging) for further understanding of how to use GDB both in the CLI and through an IDE. | ||
|
||
## pwndbg | ||
|
||
[pwndbg](https://github.com/pwndbg/pwndbg) is a GDB plugin that provides a number of useful features for debugging and exploiting binaries. | ||
It makes GDB easier to use and infinitely more powerful. | ||
It will become more useful as we progress through the lab sessions. | ||
|
||
Cheatsheet [gdb + pwndbg](https://cheatography.com/superkojiman/cheat-sheets/gdb-pwndbg/); pwndbg [features](https://github.com/pwndbg/pwndbg/blob/dev/FEATURES.md) | ||
|
||
```pwndbg | ||
pwndbg> show context-sections | ||
'regs disasm code ghidra stack backtrace expressions' | ||
# for smaller terminals | ||
pwndbg> set context-sections 'regs code stack' | ||
# display memory area in hex + ASCII | ||
pwndbg> hexdump $ecx | ||
# display stack | ||
pwndbg> stack | ||
# permanently display memory dump of 8 bytes | ||
pwndbg> ctx-watch execute "x/8xb &msg" | ||
# recommended settings in .gdbinit | ||
set context-sections 'regs code expressions' | ||
set show-flags on | ||
set dereference-limit 1 | ||
``` |
1 change: 1 addition & 0 deletions
1
chapters/memory-layout/memory-operations/demos/array-vs-pointer/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/array_vs_pointer |
22 changes: 22 additions & 0 deletions
22
chapters/memory-layout/memory-operations/demos/array-vs-pointer/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
CC = gcc | ||
CFLAGS = -Wall -g | ||
LDFLAGS = | ||
|
||
TARGET_EXEC = array_vs_pointer | ||
|
||
SRCS := $(shell find $(SRC_DIRS) -name "*.c") | ||
OBJS := $(SRCS:.c=.o) | ||
|
||
$(info OBJS is $(OBJS)) | ||
$(info SRCS is $(SRCS)) | ||
|
||
$(TARGET_EXEC): $(OBJS) | ||
$(CC) $(OBJS) -o $@ $(LDFLAGS) | ||
|
||
.o: %.c | ||
$(CC) $(CFLAGS) $(LDFLAGS) -c $< -o $@ | ||
|
||
.PHONY: clean | ||
|
||
clean: | ||
$(RM) -r *.o $(TARGET_EXEC) |
20 changes: 20 additions & 0 deletions
20
chapters/memory-layout/memory-operations/demos/array-vs-pointer/array_vs_pointer.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
#include <stdio.h> | ||
|
||
char v[] = "ana are mere"; | ||
char *p = "ana are mere"; | ||
|
||
int main(void) | ||
{ | ||
printf("sizeof(v): %zu\n", sizeof(v)); | ||
printf("sizeof(p): %zu\n", sizeof(p)); | ||
|
||
printf("v[1]: %c\n", v[1]); | ||
printf("p[1]: %c\n", p[1]); | ||
|
||
v[1] = 'd'; | ||
// p[1] = 'd'; /* this seg faults */ | ||
|
||
return 0; | ||
} |
14 changes: 14 additions & 0 deletions
14
chapters/memory-layout/memory-operations/drills/tasks/delete_first/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Deleting the First Occurrence of a Pattern from a String | ||
|
||
You will solve the exercise starting from the `delete-first.c` file located in the `drills/tasks/delete-first/support` directory. | ||
|
||
Given a string and a pattern, implement the `delete_first(char *s, char *pattern)` function that returns the string obtained by removing the first occurrence of the pattern in `s`. | ||
|
||
> **NOTE:** For `s = "Ana are mere"` and `pattern = "re"`, the function should return the string "Ana a mere". | ||
> | ||
> **IMPORTANT:** Warning | ||
> | ||
> ```c | ||
> char *s = "Ana are mere" // allocates the string in a read-only memory area (immutable content); | ||
> char s[] = "Ana are mere" // allocates the string in a read-write memory area (modifiable content); | ||
> ``` |
1 change: 1 addition & 0 deletions
1
chapters/memory-layout/memory-operations/drills/tasks/delete_first/solution/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/delete_first |
1 change: 1 addition & 0 deletions
1
chapters/memory-layout/memory-operations/drills/tasks/delete_first/solution/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../support/Makefile |
52 changes: 52 additions & 0 deletions
52
chapters/memory-layout/memory-operations/drills/tasks/delete_first/solution/delete_first.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
#include <stdio.h> | ||
#include <string.h> | ||
#include <stdlib.h> | ||
#include <assert.h> | ||
|
||
char *delete_first(char *s, char *pattern) | ||
{ | ||
char *found = strstr(s, pattern); | ||
|
||
/** | ||
* Handle the case where the pattern does not appear in the | ||
* string of characters. | ||
*/ | ||
if (!found) | ||
return strdup(s); | ||
|
||
/* number of characters before the first occurrence of the pattern */ | ||
int nbefore = found - s; | ||
/* number of characters to be removed */ | ||
int nremoved = strlen(pattern); | ||
/* Allocate exactly what we need. */ | ||
char *result = malloc(strlen(s) + 1 - nremoved); | ||
|
||
/* Check if the allocation worked */ | ||
if (result == NULL) { | ||
perror("malloc"); | ||
exit(1); | ||
} | ||
|
||
/* Construct the result */ | ||
strncpy(result, s, nbefore); | ||
strcpy(result + nbefore, found + nremoved); | ||
|
||
return result; | ||
} | ||
|
||
int main(void) | ||
{ | ||
/** | ||
* Replace *s with s[], because *s allocated the string in a | ||
* read-only memory area (.rodata), and the delete_first() function | ||
* needs to modify the string s | ||
*/ | ||
char s[] = "Ana are mere"; | ||
char *pattern = "re"; | ||
|
||
printf("%s\n", delete_first(s, pattern)); | ||
|
||
return 0; | ||
} |
1 change: 1 addition & 0 deletions
1
chapters/memory-layout/memory-operations/drills/tasks/delete_first/support/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/delete_first |
Oops, something went wrong.