Skip to content

Commit

Permalink
make stack trace print function names
Browse files Browse the repository at this point in the history
  • Loading branch information
jakeSteinburger committed Jul 28, 2024
1 parent feb0e13 commit 947f522
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 62 deletions.
11 changes: 4 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,10 @@ override KCPPFLAGS := \
-MP

override KLDFLAGS += \
-nostdlib \
-Wl,-m,elf_x86_64 \
-Wl,-nostdlib \
-Wl,-pie \
-Wl,-z,text \
-Wl,-z,max-page-size=0x1000 \
-Wl,-T,linker.ld
-Wl,-g \
-Wl,-T,linker.ld \
-nostdlib \
-Wl,-nostdlib

override KNASMFLAGS += \
-Wall \
Expand Down
6 changes: 6 additions & 0 deletions compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,11 @@ echo "Complete! disk.img should now be in the current directory and bootable wit
echo "Size of kernel: "
du -h bin/SpecOS

# if image could be built, run it in qemu
if test -f "bin/SpecOS"; then
qemu-system-x86_64 disk.img -d int -serial stdio --no-reboot --no-shutdown -accel kvm
fi

# delete old stuff
rm -rf bin obj limine /mnt/specos

10 changes: 10 additions & 0 deletions kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ void _start() {
// this is commented out cos paging doesn't work yet and it's still in progress.
//writestring("\nInitiating paging...");
//initPaging();
char buffer[10];
uint64_t tableSingle;
for (int i = 0; i < 5; i++) {
for (int y = 0; y < 10; y++)
buffer[y] = 0;
tableSingle = *(uint64_t*)&(kernel.GDT)[i];
uint64_to_hex_string((uint64_t)tableSingle, buffer);
writestring("\nGDT contents: 0x");
writestring(buffer);
}
test_userspace();
for (;;);
}
60 changes: 25 additions & 35 deletions linker.ld
Original file line number Diff line number Diff line change
@@ -1,55 +1,45 @@
/* Tell the linker that we want an x86_64 ELF64 output file */
OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64)

/* We want the symbol _start to be our entry point */
ENTRY(_start)
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */
}

SECTIONS
{
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
/* and because that is what the Limine spec mandates. */
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
/* that is the beginning of the region. */
/* Additionally, leave space for the ELF headers by adding SIZEOF_HEADERS to the */
/* base load address. */
. = 0xffffffff80000000 + SIZEOF_HEADERS;
.rodata ALIGN(CONSTANT(MAXPAGESIZE)) : {
*(.rodata .rodata.*)
}
. = 0xffffffff80000000;

.text ALIGN(CONSTANT(MAXPAGESIZE)) : {
.text : {
*(.text .text.*)
}
} :text

.data ALIGN(CONSTANT(MAXPAGESIZE)) : {
*(.data .data.*)
. += CONSTANT(MAXPAGESIZE);

/* Place the sections that contain the Limine requests as part of the .data */
/* output section. */
KEEP(*(.requests_start_marker))
KEEP(*(.requests))
KEEP(*(.requests_end_marker))
}
.rodata : {
*(.rodata .rodata.*)
} :rodata

. += CONSTANT(MAXPAGESIZE);

.data : {
*(.data .data.*)
} :data

/* Dynamic section for relocations and other PIE related information. */
.dynamic : {
*(.dynamic)
}
} :data :dynamic

/* NOTE: .bss needs to be the last thing mapped to the data PHDR, otherwise lots of */
/* unnecessary zeros will be written to the binary. */
/* If you need, for example, .init_array and .fini_array, those should be placed */
/* above this. */
.bss ALIGN(CONSTANT(MAXPAGESIZE)) : {
.bss : {
*(.bss .bss.*)
*(COMMON)
}

/* Discard the program interpreter section since we do not need one. This is */
/* more or less equivalent to the --no-dynamic-linker linker flag, except that it */
/* works with ld.gold. */
} :data
/DISCARD/ : {
*(.interp)
*(.eh_frame)
*(.note .note.*)
}
}
73 changes: 55 additions & 18 deletions sys/panic.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,66 @@ struct elfSectionHeader {
uint32_t info;
uint64_t addressAlign;
uint64_t entrySize;
};
} __attribute__ ((packed));

void getFunctionName() {
struct symtabEntry {
uint32_t name;
uint8_t info;
uint8_t other;
uint16_t shndx;
uint64_t value;
uint64_t size;
};// __attribute__((packed));

void assert(bool condition) {
if (condition) {
writestring("\nASSERT: True\n");
} else {
writestring("\nFailed assert.\n");
asm("cli; hlt");
}
}

void getFunctionName(uint64_t address) {
struct limine_kernel_file_response kernelElfResponse = *kernelElfRequest.response;
struct limine_file kernelFile = *kernelElfResponse.kernel_file;
char* kernelFileStart = (char*) kernelFile.address;
uint64_t kernelFileLength = kernelFile.size;
char buffer[19];
char buffer2[19];
uint64_to_hex_string((uint64_t) kernelFileStart, buffer2);
uint64_to_hex_string(kernelFileLength, buffer);
buffer[18] = 0;
printf("\nKernel address: 0x%s\nKernel size: 0x%s\n", buffer2, buffer);
if (kernelFileStart[0] == 0x7F && kernelFileStart[1] == 'E' && kernelFileStart[2] == 'L' && kernelFileStart[3] == 'F' &&
kernelFileStart[4] == 2) {
// it's a valid 64 bit elf file!
// parse the section header table
char* sectionHeaderOffset = (char*)((uint64_t)(*(char*)&kernelFileStart[40]) & 0xFFFFFFFFFFFFFF);
uint16_t sectionHeaderNumEntries = (kernelFileStart[60] << 8) | kernelFileStart[61];

struct elfSectionHeader *sectionHeaderOffset = (struct elfSectionHeader*)(*(uint64_t*)((kernelFileStart + 40)) + ((uint64_t)kernelFileStart));
uint16_t sectionHeaderNumEntries = *(uint16_t*)(kernelFileStart + 60);
// parse the section header string table
uint16_t sectionHeaderStringTableIndex = *(uint16_t*)(kernelFileStart + 62);
char* sectionHeaderStringTableOffset = (char*)(sectionHeaderOffset[sectionHeaderStringTableIndex].offset + ((uint64_t)kernelFileStart));
// now look through each section header entry, comparing the name, and find the offset of .strtab and .symtab
struct symtabEntry *symtabOffset = 0;
char* strtabOffset = 0;
uint64_t symtabIndex = 0;
for (int i = 0; i < sectionHeaderNumEntries; i++) {
// check if it's .symtab or .strtab by comparing it's string in the section header string table
if (strcmp(&sectionHeaderStringTableOffset[sectionHeaderOffset[i].name], ".strtab")) {
strtabOffset = (char*)(sectionHeaderOffset[i].offset + (uint64_t)kernelFileStart);
}
if (strcmp(&sectionHeaderStringTableOffset[sectionHeaderOffset[i].name], ".symtab")) {
symtabOffset = (struct symtabEntry*)(sectionHeaderOffset[i].offset + (uint64_t)kernelFileStart);
symtabIndex = i;
}
}
// now go through .symtab, looking for an entry who's address is equal to `address`
for (int i = 0; i < sectionHeaderOffset[symtabIndex].size / sizeof(struct symtabEntry); i++) {
if (address >= symtabOffset[i].value && address < symtabOffset[i].value + symtabOffset[i].size) {
// found! parse the string table to find the actual thingy
printf(" %s\n", (&strtabOffset[symtabOffset[i].name]));
return;
}
}
// if it got to this point, it's invalid.
printf(" <INVALID>\n");
} else {
printf(" <INVALID>");
printf(" <INVALID>");
}
}

Expand All @@ -67,12 +105,10 @@ void stackTrace(int m) {
writestring("\n\n==== Stack Trace: ====\n\n"); // 22
struct stackFrame *stack;
asm("mov %%rbp, %0" : "=r"(stack));
char buffer[19];
for (unsigned int f = 0; stack && f < m; f++) {
memset(buffer, 0, 18);
uint64_to_hex_string(stack->rip, buffer);
buffer[18] = '\0';
printf(" 0x%s\n", buffer);
printf(" 0x%x", stack->rip);
if (stack->rip)
getFunctionName(stack->rip);
stack = stack->rbp;
}
}
Expand Down Expand Up @@ -139,6 +175,7 @@ void kpanic(char* exception) {
writestring("\n\n== Last 10 stdio outputs: ==\n\n");
for (int i = 0; i < 10; i++)
writestring(kernel.last10[i]);
getFunctionName();*/
*/

asm("cli; hlt");
}
2 changes: 2 additions & 0 deletions utils/include/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ int compareDifferentLengths(const char *longer, const char *shorter);
char* charToStr(char character);
void uint16_to_string(uint16_t num, char *str);
void uint32_to_string(uint32_t num, char *str);
void uint64_to_string(uint64_t num, char *str);
void memset(uint8_t *array, uint8_t value, size_t size);
void uint32_to_hex_string(uint32_t num, char *str);
void uint64_to_hex_string(uint64_t num, char *str);
bool strcmp(const char* str1, const char* str2);

#endif

8 changes: 7 additions & 1 deletion utils/printf.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@ void printf(char* format, ...) {
i++;
char buffer[10];
if (format[i] == 'd' || format[i] == 'i') {
uint32_to_string(va_arg(args, int), buffer);
uint64_to_string(va_arg(args, uint64_t), buffer);
buffer[9] = 0;
writestring(buffer);
} else if (format[i] == 'c') {
writestring(charToStr(va_arg(args, char)));
} else if (format[i] == 'x') {
char bufferx[20];
bufferx[19] = 0;
uint64_to_hex_string(va_arg(args, uint64_t), bufferx);
writestring(bufferx);
} else if (format[i] == 's') {
writestring(va_arg(args, char*));
}
Expand Down
26 changes: 25 additions & 1 deletion utils/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ size_t strlen(const char* str)
return len;
}

bool strcmp(const char* str1, const char* str2) {
int str1len = strlen(str1);
int str2len = strlen(str2);
if (str1len != str2len) return false;
for (int c = 0; c < str1len && c < str2len; c++) {
if (str1[c] != str2[c]) return false;
}
return true;
}

void memset(uint8_t *array, uint8_t value, size_t size) {
for (size_t i = 0; i < size; i++) {
Expand Down Expand Up @@ -146,7 +155,7 @@ void uint64_to_hex_string(uint64_t num, char *str) {
}


int get_num_length(uint32_t num) {
int get_num_length(uint64_t num) {
int length = 0;
do {
length++;
Expand All @@ -155,6 +164,21 @@ int get_num_length(uint32_t num) {
return length;
}

void uint64_to_string(uint64_t num, char* str) {
// Get the length of the number
int length = get_num_length(num);

// Null-terminate the string
str[length] = '\0';

// Fill the buffer with digits in reverse order
int index = length - 1;
do {
str[index--] = '0' + (num % 10);
num /= 10;
} while (num > 0);
}

void uint32_to_string(uint32_t num, char* str) {
// Get the length of the number
int length = get_num_length(num);
Expand Down

0 comments on commit 947f522

Please sign in to comment.