This repository has been archived by the owner on Jan 14, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: complete lab 6 - observation of process address space
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
Showing
4 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
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,2 @@ | ||
build | ||
.gdb_history |
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,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 |
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,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; | ||
} |
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,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; | ||
} |