Skip to content
This repository has been archived by the owner on Jan 14, 2025. It is now read-only.

Commit

Permalink
feat: complete lab 6 - observation of process address space
Browse files Browse the repository at this point in the history
This commit finalizes the implementation for lab 6, which involves observing the process address space.

The following files have been added to support this task:
- lab6-memory/.gitignore: A configuration file to ignore certain files and directories that are not relevant to the version control.
- lab6-memory/Makefile: A Makefile to compile and build the source code for observing the process address space.
- lab6-memory/src/main.c: The main source file containing the logic to allocate some memory.
- lab6-memory/src/util.cpp: A utility source file that provides additional functions to support the observation process.
  • Loading branch information
agicy committed Dec 12, 2024
1 parent 22d1e44 commit 46168f8
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lab6-memory/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build
.gdb_history
18 changes: 18 additions & 0 deletions lab6-memory/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
C := gcc
CXX := g++

build:
mkdir -p build
$(C) src/main.c -std=c17 -O0 \
-Wall -Wextra -Werror \
-fno-stack-protector -no-pie \
-g \
-o build/main
$(CXX) src/util.cpp -std=c++20 -O2 \
-Wall -Wextra -Werror \
-o build/util

clean:
rm -rf build

.PHONY: build clean
89 changes: 89 additions & 0 deletions lab6-memory/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include <assert.h>
#include <pthread.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define STACK_ARRAY_SIZE (1 << 15) // 32 KiB
#define HEAP_ARRAY_SIZE (1 << 25) // 32 MiB
#define THREAD_COUNT 2

pthread_mutex_t mutex_output;

static inline void output(const char *fmt, ...) {
pthread_mutex_lock(&mutex_output);

va_list args;
va_start(args, fmt);
vprintf(fmt, args);
putchar('\n');
fflush(stdout);
va_end(args);

pthread_mutex_unlock(&mutex_output);
}

const char *string_literal_1 = "i will be put in the .rodata segment.";
const char *string_literal_2 = "i will be put in the .rodata segment.";
const char *string_literal_3 = "i will be the different one!";
const int integer_constant = 42;

int bss_integer;
double bss_real;

int integer = 2022212720;
double real = 2022211363;

static inline void easy_to_break() {}

static inline void *task(void *arg) {
size_t id = *(size_t *)arg;

int array_on_stack[STACK_ARRAY_SIZE];
int *array_on_heap = malloc(HEAP_ARRAY_SIZE * sizeof(int));
output("Thread %zu started, stack array address: %p, heap array address: %p", id, array_on_stack, array_on_heap);

pthread_cleanup_push(free, array_on_heap);

easy_to_break();

pthread_cleanup_pop(1);
pthread_exit(NULL);
}

int main() {
pthread_mutex_init(&mutex_output, NULL);
int array_on_stack[STACK_ARRAY_SIZE];
int *array_on_heap = malloc(HEAP_ARRAY_SIZE * sizeof(int));
pthread_t threads[THREAD_COUNT];
size_t ids[THREAD_COUNT];

output("Hello, World! My pid is %d", getpid());
output("Stack array address: %p", array_on_stack);
output("Heap array address: %p", array_on_heap);

output("Threads creating...");
for (size_t i = 0; i < THREAD_COUNT; i++) {
ids[i] = i;
pthread_create(&threads[i], NULL, task, &ids[i]);
}

easy_to_break();

output("Threads joining...");
for (size_t i = 0; i < THREAD_COUNT; i++) {
pthread_cancel(threads[i]);
pthread_join(threads[i], NULL);
}

output("Bye, World!");

free(array_on_heap), array_on_heap = NULL;
pthread_mutex_destroy(&mutex_output);

easy_to_break();

return 0;
}
90 changes: 90 additions & 0 deletions lab6-memory/src/util.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <cstdint>
#include <fcntl.h>
#include <format>
#include <fstream>
#include <iostream>
#include <sstream>
#include <unistd.h>
#include <vector>

struct pagemap_entry_t {
uint64_t pfn : 55;
unsigned int soft_dirty : 1;
unsigned int file_page : 1;
unsigned int swapped : 1;
unsigned int present : 1;
};

static inline auto get_pagemap_entry(int pagemap_fd, uintptr_t page_number) -> pagemap_entry_t {
pagemap_entry_t entry;
size_t nread = 0;
uint64_t data;
while (nread < sizeof(data)) {
ssize_t result = pread(pagemap_fd, ((uint8_t *)&data) + nread, sizeof(data) - nread, page_number * sizeof(data) + nread);
if (result <= 0) {
std::cerr << "Failed to read pagemap file" << std::endl;
abort();
}
nread += result;
}

entry.pfn = data & ((1ull << 55) - 1);
entry.soft_dirty = (data >> 55) & 1;
entry.file_page = (data >> 61) & 1;
entry.swapped = (data >> 62) & 1;
entry.present = (data >> 63) & 1;
return entry;
}

int main() {
pid_t pid;
std::cout << "Please input pid: " << std::endl;
std::cin >> pid;

std::string pagemap_path = std::format("/proc/{}/pagemap", pid);
std::cout << pagemap_path << std::endl;

int pagemap_fd = open(pagemap_path.c_str(), O_RDONLY);
if (pagemap_fd == -1) {
std::cerr << "Failed to open pagemap file" << std::endl;
abort();
}

auto get_physical_address = [&](size_t virtual_address) -> void {
const size_t page_size = sysconf(_SC_PAGESIZE);

const size_t page_number = virtual_address / page_size, offset = virtual_address % page_size;

const pagemap_entry_t entry = get_pagemap_entry(pagemap_fd, page_number);

if (!entry.present) {
std::cerr << "Page not present" << std::endl;
return;
}

std::cout
<< std::format("frame_number = 0x{:016x}, soft_dirty = {}, file_page = {}, swapped = {}, present = {}",
static_cast<uint64_t>(entry.pfn),
static_cast<bool>(entry.soft_dirty),
static_cast<bool>(entry.file_page),
static_cast<bool>(entry.swapped),
static_cast<bool>(entry.present))
<< std::endl;

const size_t frame_number = entry.pfn;
const size_t physical_address = frame_number * page_size + offset;

std::cout << std::format("Physical Address: 0x{:016x}\n", physical_address) << std::endl;
return;
};

while (true) {
size_t virtual_address;
std::cout << "Please input virtual address: " << std::endl;
std::cin >> std::hex >> virtual_address;
get_physical_address(virtual_address);
}

close(pagemap_fd);
return 0;
}

0 comments on commit 46168f8

Please sign in to comment.