Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add files to Arena lab #77

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ topic/software-stack:
- 'chapters/software-stack/**/*'

topic/data:
- 'content/chapters/data/**/*'
- 'chapters/data/**/*'

topic/compute:
- 'content/chapters/compute/**/*'
Expand Down
2 changes: 2 additions & 0 deletions chapters/data/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/_site
/slides.md
33 changes: 33 additions & 0 deletions chapters/data/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
RVMD = reveal-md
MDPP = markdown-pp
FFMPEG = ffmpeg

SLIDES ?= slides.mdpp
SLIDES_OUT ?= slides.md
MEDIA_DIR ?= media
SITE ?= _site
OPEN ?= xdg-open

.PHONY: all html clean videos

all: videos html

html: $(SITE)

$(SITE): $(SLIDES)
$(MDPP) $< -o $(SLIDES_OUT)
$(RVMD) $(SLIDES_OUT) --static $@

videos:
for TARGET in $(TARGETS); do \
$(FFMPEG) -framerate 0.5 -f image2 -y \
-i "$(MEDIA_DIR)/$$TARGET/$$TARGET-%d.svg" -vf format=yuv420p $(MEDIA_DIR)/$$TARGET-generated.gif; \
done

open: $(SITE)
$(OPEN) $</index.html

clean:
-rm -f $(MEDIA_DIR)/*-generated.gif
-rm -f *~
-rm -fr $(SITE) $(SLIDES_OUT)
37 changes: 37 additions & 0 deletions chapters/data/arena/drills/questions/operators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Operator Overloading

## Question Text

How many constructor calls, copy constructor calls, assignment operator calls and destructor calls does the following program issue?

```d
Obj quiz(Obj o1, Obj o2)
{
o2 = o1;
return o2;
}
void main()
{
Obj b = quiz(o1, o2);
}
```

## Question Answers

+ constructor calls = 0, copy constructor calls = 3, assignment operator calls = 1, destructor calls = 3

- constructor calls = 1, copy constructor calls = 2, assignment operator calls = 1, destructor calls = 2

- constructor calls = 0, copy constructor calls = 2, assignment operator calls = 1, destructor calls = 2

- constructor calls = 0, copy constructor calls = 3, assignment operator calls = 1, destructor calls = 1

## Feedback

- There are no constructor calls because there is no object construction when using `int`.

- There are 3 copy constructor calls: for passing `o1`, for passing `o2`, and for returning `o2`.

- There is 1 assignment operator call for `o2 = o1`.

- There are 3 destructor calls, because each constructed object needs to be destroyed.
45 changes: 45 additions & 0 deletions chapters/data/arena/drills/tasks/access-counter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## Access Counter

Navigate to the `support/access-counter/` directory.

Your goal is to update the `src/access_counter.c` source code file to capture memory access exceptions (i.e. the `SIGSEGV` signal) and to update page permissions in order for the access to eventually succeed.
Use `mprotect` to update the protection of the pages in stages: read, write and then exec.
Each time an update is made, the `counter` variable is increased;
this is used for testing.

The signal handler is already in place as the `access_handler()` function.
It is called any time a `SIGSEGV` signal is being sent out to the current process.
You will update the handler by following the `TODO` comments and instructions here.

The `pages` array stores information about accessed pages.
Assume the `MAX_PAGES` size of the array is enough to store information.
When an existing page is accessed and causes a memory exception, the permission is update, in the stages mentioned above: read, write, and then exec.
When a new page is accessed, a new entry is filled in the `pages` array, initialized with read protection.
Use `mmap()` to reserve virtual pages.
Use anonymous mapping (i.e. the `MAP_ANONYMOUS`) flag.
Use any permissions required.

To test it, enter the `tests/` directory and run:

```console
make check
```

In case of a correct solution, you will get an output such as:

```text
./run_all_tests.sh
test_acess_read ........................ passed ... 9
test_acess_write ........................ passed ... 9
test_acess_exec ........................ passed ... 10
test_acess_read_write ........................ passed ... 12
test_acess_read_exec ........................ passed ... 12
test_acess_write_exec ........................ passed ... 12
test_acess_exec_read ........................ passed ... 12
test_acess_exec_write ........................ passed ... 12
test_acess_write_read ........................ passed ... 12

Total: 100/100
```

If you're having difficulties solving this exercise, go through [this](../../../reading/arena.md) reading material.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CFLAGS ?= -Wall -Wextra
CPPFLAGS ?= -I../utils

.PHONY: all clean

all: access_counter.o ../utils/log/log.o

access_counter.o: access_counter.c ../utils/utils.h ../utils/log/log.h

../utils/log/log.o: ../utils/log/log.c ../utils/log/log.h

clean:
-rm -f access_counter.o ../utils/log/log.o
-rm -f *~
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// SPDX-License-Identifier: BSD-3-Clause

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>

#include "utils.h"
#include "access_counter.h"

struct page_info {
int prot;
void *start;
};

unsigned long counter;

#define MAX_PAGES 16
static struct page_info pages[MAX_PAGES];
static size_t num_pages;

/* This is useful for filling the contents when execution rights are provided. */
static void do_nothing(void)
{
}

/*
* The actual SIGSEVG handler.
*/
static void access_handler(int signum, siginfo_t *si, void *arg)
{
long page_size = sysconf(_SC_PAGESIZE);
void *start;
int rc;
unsigned int i;

log_debug("Enter handler");

counter++;

if (signum != SIGSEGV) {
fprintf(stderr, "Unable to handle signal %d (%s)\n", signum, strsignal(signum));
return;
}

/* TODO 2: Obtain page strart address in start variable. */
start = (void *) ((unsigned long) si->si_addr & ~0xFFFUL);
log_debug("start: %p", start);

for (i = 0; i < num_pages; i++)
if (pages[i].start == start)
break;

if (i >= num_pages && i < MAX_PAGES) {
pages[i].start = start;
pages[i].prot = PROT_NONE;
num_pages += 1;
}

log_debug("i = %u", i);

/* TODO 21: Update page proctections with mprotect(). */
switch (pages[i].prot) {
case PROT_NONE:
rc = mprotect(start, page_size, PROT_READ);
DIE(rc < 0, "mprotect");
pages[i].prot = PROT_READ;
break;
case PROT_READ:
rc = mprotect(start, page_size, PROT_READ | PROT_WRITE);
DIE(rc < 0, "mprotect");
pages[i].prot = PROT_WRITE;
break;
case PROT_WRITE:
rc = mprotect(start, page_size, PROT_READ | PROT_WRITE | PROT_EXEC);
DIE(rc < 0, "mprotect");
/* Optimistically copy 64 bytes of code. Should be more than enough. */
memcpy(start, do_nothing, 64);
pages[i].prot = PROT_EXEC;
break;
default:
break;
}
}

void register_sigsegv_handler(void)
{
struct sigaction sa;
int rc;

memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = access_handler;
sa.sa_flags = SA_SIGINFO;

rc = sigaction(SIGSEGV, &sa, NULL);
DIE(rc < 0, "sigaction");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* SPDX-License-Identifier: BSD-3-Clause */

#ifndef ACCESS_PRINTER_H_
#define ACCESS_PRINTER_H_ 1

extern unsigned long counter;
void register_sigsegv_handler(void);

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exclude_files=log\.c
Loading