mirror of https://github.com/flysand7/ciabatta.git
loader retrieve stack bounds from /proc/self/maps
This commit is contained in:
parent
7929779df6
commit
653342a30a
|
@ -14,5 +14,5 @@ _dlstart:
|
|||
; `call` pushes 8-byte value onto the stack
|
||||
; by pushing an 8-bit value ourselves we can make
|
||||
; sure the stack is aligned after rbp push in prologue
|
||||
sub rsp, 8
|
||||
push 0
|
||||
|
||||
|
|
|
@ -16,3 +16,4 @@
|
|||
#define O_FSYNC O_SYNC
|
||||
#define O_ASYNC 020000
|
||||
#define O_CLOEXEC 02000000
|
||||
#define O_DIRECT 040000
|
|
@ -380,15 +380,15 @@ static inline i64 _syscall6(i64 n, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5, i64 a
|
|||
#define SYS_rt_tgsigqueueinfo 297
|
||||
#define SYS_perf_event_open 298
|
||||
|
||||
static inline i64 sys_read(u32 fd, char *buf, u64 count) {
|
||||
static inline i32 sys_read(u32 fd, char *buf, u64 count) {
|
||||
return syscall(SYS_read, fd, buf, count);
|
||||
}
|
||||
|
||||
static inline i64 sys_write(u32 fd, char const *buf, u64 count) {
|
||||
static inline i32 sys_write(u32 fd, char const *buf, u64 count) {
|
||||
return syscall(SYS_write, fd, buf, count);
|
||||
}
|
||||
|
||||
static inline i64 sys_open(char const *filename, int flags, int mode) {
|
||||
static inline i32 sys_open(char const *filename, int flags, int mode) {
|
||||
return syscall(SYS_open, filename, flags, mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "../src/cia-mem/arena.c"
|
||||
#include "../src/cia-mem/pool.c"
|
||||
|
||||
#include "stack.c"
|
||||
|
||||
struct Elf_Image typedef Elf_Image;
|
||||
struct Elf_Image {
|
||||
Cia_Arena arena;
|
||||
|
@ -148,6 +150,14 @@ void loader_entry(Loader_Info *ld_info) {
|
|||
if(fd != 0) {
|
||||
sys_close(fd);
|
||||
}
|
||||
// Get the information about the main thread stack
|
||||
if(linux_read_stack_info()) {
|
||||
printf("ERROR: failed to read /proc/self/maps to get the stack info\n");
|
||||
sys_exit(1);
|
||||
}
|
||||
_dbg_printf("Received stack: %x-%x\n", stack_info.start_addr, stack_info.end_addr);
|
||||
u64 *ptr = (void *)stack_info.start_addr;
|
||||
// *ptr = 1245;
|
||||
// Find .dynamic section
|
||||
{
|
||||
u8 *phdr = (void *)aux[AT_PHDR];
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
|
||||
#define VM_READ 0x00000001
|
||||
#define VM_WRITE 0x00000002
|
||||
#define VM_EXEC 0x00000004
|
||||
#define VM_SHARED 0x00000008
|
||||
|
||||
struct File_Buffer typedef File_Buffer;
|
||||
struct File_Buffer {
|
||||
int fd;
|
||||
char *data;
|
||||
u64 data_size;
|
||||
u64 last_read_size;
|
||||
u64 offset;
|
||||
int last_char;
|
||||
};
|
||||
|
||||
struct Stack_Info typedef Stack_Info;
|
||||
struct Stack_Info {
|
||||
bool stack_found;
|
||||
u64 start_addr;
|
||||
u64 end_addr;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
static Stack_Info stack_info;
|
||||
|
||||
static int read_char(File_Buffer *buffer) {
|
||||
// If we need to read more stuff, fetch it from the file
|
||||
if(buffer->offset >= buffer->last_read_size) {
|
||||
int result = sys_read(buffer->fd, buffer->data, buffer->data_size);
|
||||
if(result < 0) {
|
||||
_dbg_printf("result < 0");
|
||||
return -1;
|
||||
}
|
||||
if(result == 0) {
|
||||
buffer->last_char = -1;
|
||||
return buffer->last_char;
|
||||
}
|
||||
int read_size = result;
|
||||
buffer->data[read_size] = 0;
|
||||
buffer->last_read_size = read_size;
|
||||
buffer->offset = 0;
|
||||
}
|
||||
// Return the character from a buffer
|
||||
u64 cur_offset = buffer->offset;
|
||||
buffer->offset += 1;
|
||||
buffer->last_char = buffer->data[cur_offset];
|
||||
_dbg_printf("%c", buffer->last_char);
|
||||
return buffer->last_char;
|
||||
}
|
||||
|
||||
static int char_is_hex(int ch) {
|
||||
if('0' <= ch && ch <= '9') return 1;
|
||||
if('a' <= ch && ch <= 'f') return 1;
|
||||
if('A' <= ch && ch <= 'F') return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int char_to_hex(int ch) {
|
||||
if(ch <= '9') {
|
||||
return ch - '0';
|
||||
}
|
||||
return ch - 'a' + 10;
|
||||
}
|
||||
|
||||
static int read_hex(File_Buffer *buffer, u64 *out_result) {
|
||||
u64 result = 0;
|
||||
int n_digits = 0;
|
||||
for(;;) {
|
||||
int ch = buffer->last_char;
|
||||
if(!char_is_hex(ch)) {
|
||||
break;
|
||||
}
|
||||
result *= 16;
|
||||
result += char_to_hex(ch);
|
||||
read_char(buffer);
|
||||
n_digits += 1;
|
||||
}
|
||||
*out_result = result;
|
||||
if(n_digits == 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_dec(File_Buffer *buffer, u64 *out_result) {
|
||||
u64 result = 0;
|
||||
int n_digits = 0;
|
||||
for(;;) {
|
||||
int ch = buffer->last_char;
|
||||
if(!('0' <= ch && ch <= '9')) {
|
||||
break;
|
||||
}
|
||||
result *= 10;
|
||||
result += ch - '0';
|
||||
read_char(buffer);
|
||||
n_digits += 1;
|
||||
}
|
||||
*out_result = result;
|
||||
if(n_digits == 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int linux_read_stack_info() {
|
||||
bool stack_found = false;
|
||||
// Initialize the buffer for buffered read
|
||||
char line_buf[1024];
|
||||
File_Buffer buffer;
|
||||
buffer.data = line_buf;
|
||||
buffer.data_size = sizeof line_buf;
|
||||
buffer.last_read_size = 0;
|
||||
buffer.offset = 0;
|
||||
// Open the file
|
||||
buffer.fd = (i32)(u32)sys_open("/proc/self/maps", 0, O_RDONLY);
|
||||
_dbg_printf("/proc/self/maps fd: %d\n", (i64)(i32)buffer.fd);
|
||||
if((i64)(i32)buffer.fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
// Read the first character
|
||||
if(read_char(&buffer) < 0) {
|
||||
_dbg_printf("\nERROR: (/proc/self/maps) Failed reading char at offset %x\n", buffer.offset);
|
||||
return -1;
|
||||
}
|
||||
// Start reading the lines until we hit the stack
|
||||
char desired_name[] = "[stack]";
|
||||
while(!stack_found && buffer.last_char != -1) {
|
||||
// If we're doing n-th iteration, consume the newline
|
||||
if(buffer.last_char == '\n') {
|
||||
read_char(&buffer);
|
||||
}
|
||||
// Read the start and end addr of the section
|
||||
u64 start_addr = 0;
|
||||
u64 end_addr = 0;
|
||||
if(read_hex(&buffer, &start_addr)) {
|
||||
_dbg_printf("|\nERROR: read_hex failed to read start_addr\n");
|
||||
return -1;
|
||||
}
|
||||
if(buffer.last_char != '-') {
|
||||
_dbg_printf("|\nERROR: expected '-', didn't see it\n");
|
||||
return -1;
|
||||
}
|
||||
if(read_char(&buffer) < 0) {
|
||||
_dbg_printf("|\nERROR: read_char failed after saw '-'\n");
|
||||
return -1;
|
||||
}
|
||||
if(read_hex(&buffer, &end_addr) < 0) {
|
||||
_dbg_printf("|\nERROR: read_hex failed to read end_addr\n");
|
||||
return -1;
|
||||
}
|
||||
// Skip whitespace
|
||||
if(read_char(&buffer) < 0) {
|
||||
_dbg_printf("|\nERROR: read_char failed skipping whitespace after addrs\n");
|
||||
return -1;
|
||||
}
|
||||
// Read the flags
|
||||
u32 flags = 0;
|
||||
if(buffer.last_char == 'r') {
|
||||
flags |= VM_READ;
|
||||
}
|
||||
read_char(&buffer);
|
||||
if(buffer.last_char == 'w') {
|
||||
flags |= VM_WRITE;
|
||||
}
|
||||
read_char(&buffer);
|
||||
if(buffer.last_char == 'x') {
|
||||
flags |= VM_EXEC;
|
||||
}
|
||||
read_char(&buffer);
|
||||
if(buffer.last_char == 's') {
|
||||
flags |= VM_SHARED;
|
||||
}
|
||||
read_char(&buffer);
|
||||
// Skip 15 characters corresponding to `offset` and `device` fields
|
||||
for(int i = 0; i != 16; ++i) {
|
||||
read_char(&buffer);
|
||||
}
|
||||
// Read `inode` field
|
||||
u64 inode = 0;
|
||||
if(read_dec(&buffer, &inode)) {
|
||||
_dbg_printf("|\nERROR reading inode field: %c\n", buffer.last_char);
|
||||
return -1;
|
||||
}
|
||||
// If the line terminates here, skip this line
|
||||
if(buffer.last_char == '\n' || buffer.last_char == -1) {
|
||||
continue;
|
||||
}
|
||||
// Skip whitespace
|
||||
while(buffer.last_char == ' ') {
|
||||
read_char(&buffer);
|
||||
}
|
||||
// Read the name of the mapping
|
||||
char name_buf[256];
|
||||
u64 name_buf_size = sizeof name_buf;
|
||||
int name_len = 0;
|
||||
while(name_len < name_buf_size && buffer.last_char != '\n' && buffer.last_char != -1)
|
||||
{
|
||||
name_buf[name_len] = buffer.last_char;
|
||||
read_char(&buffer);
|
||||
++name_len;
|
||||
}
|
||||
name_buf[name_len] = 0;
|
||||
// If the name is '[stack]' we pass the check and save the info
|
||||
if(name_len != 7) {
|
||||
continue;
|
||||
}
|
||||
for(int i = 0; i < 7; ++i) {
|
||||
if(name_buf[i] != desired_name[i]) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// We found the stack!
|
||||
stack_info.stack_found = true;
|
||||
stack_info.start_addr = start_addr;
|
||||
stack_info.end_addr = end_addr;
|
||||
stack_info.flags = flags;
|
||||
sys_close(buffer.fd);
|
||||
_dbg_printf("\nFound stack: %x-%x\n", start_addr, end_addr);
|
||||
return 0;
|
||||
}
|
||||
sys_close(buffer.fd);
|
||||
return 1;
|
||||
}
|
|
@ -15,9 +15,10 @@ void cia_mutex_lock(Cia_Mutex *mutex) {
|
|||
if(prev_tag == _CIA_MUTEX_FREE) {
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
// We should wait if:
|
||||
// (1) the mutex is contested
|
||||
// (2) this thread locking the mutex makes it contested
|
||||
// (2)
|
||||
bool should_wait = 0;
|
||||
should_wait |= (prev_tag == _CIA_MUTEX_CONT);
|
||||
should_wait |= (__sync_val_compare_and_swap(&mutex->tag, _CIA_MUTEX_LOCK, _CIA_MUTEX_CONT) != _CIA_MUTEX_FREE);
|
||||
|
@ -25,6 +26,9 @@ void cia_mutex_lock(Cia_Mutex *mutex) {
|
|||
if(should_wait) {
|
||||
_rt_sync_wait(&mutex->tag, _CIA_MUTEX_CONT, _RT_SYNC_WAIT_INFINITE);
|
||||
}
|
||||
#else
|
||||
_rt_sync_wait(&mutex->tag, _CIA_MUTEX_LOCK, _RT_SYNC_WAIT_INFINITE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,8 +44,6 @@ int thrd_func(void *arg) {
|
|||
for(int i = 0; i < 100000; ++i) {
|
||||
cia_mutex_lock(&g_mutex);
|
||||
counter += 1;
|
||||
print_int(counter);
|
||||
print_char('\n');
|
||||
cia_mutex_unlock(&g_mutex);
|
||||
}
|
||||
atomic_fetch_add(&n_completed, 1);
|
||||
|
@ -77,8 +75,6 @@ int main() {
|
|||
for(int i = 0; i < 100000; ++i) {
|
||||
cia_mutex_lock(&g_mutex);
|
||||
counter += 1;
|
||||
print_int(counter);
|
||||
print_char('\n');
|
||||
cia_mutex_unlock(&g_mutex);
|
||||
}
|
||||
atomic_fetch_add(&n_completed, 1);
|
||||
|
|
Loading…
Reference in New Issue