aboutsummaryrefslogtreecommitdiff
path: root/kernel/vdso
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/vdso')
-rw-r--r--kernel/vdso/vdso.c75
1 files changed, 35 insertions, 40 deletions
diff --git a/kernel/vdso/vdso.c b/kernel/vdso/vdso.c
index 79c2f05..6a1c198 100644
--- a/kernel/vdso/vdso.c
+++ b/kernel/vdso/vdso.c
@@ -10,13 +10,12 @@
/*
* In projects like github.com/mssola/fbos I already dealt with ELF parsing
- * myself and it was the nicest experience. Plus, in here I have to do some
+ * myself and it wasn't the nicest experience. Plus, in here I have to do some
* heave usage of some ELF sections. For this reason I will not do things
* manually and use the standard library instead.
*/
#include <elf.h>
-
// Terminate the current program with a failure exit code while also printing
// the given `message` into stderr.
__attribute__((noreturn)) void die(const char *const message)
@@ -47,13 +46,8 @@ bool is_vdso_function(const char *const name)
return false;
}
- return name[0] == '_' &&
- name[1] == '_' &&
- name[2] == 'v' &&
- name[3] == 'd' &&
- name[4] == 's' &&
- name[5] == 'o' &&
- name[6] == '_';
+ return name[0] == '_' && name[1] == '_' && name[2] == 'v' && name[3] == 'd' && name[4] == 's' &&
+ name[5] == 'o' && name[6] == '_';
}
int main(void)
@@ -63,17 +57,17 @@ int main(void)
* passed by the kernel to each program in the initial auxiliary vector (see
* getauxval(3)), via the AT_SYSINFO_EHDR tag".
*/
- void *vdso = (void *) getauxval(AT_SYSINFO_EHDR);
+ void *vdso = (void *)getauxval(AT_SYSINFO_EHDR);
if (!vdso) {
die("Could not get base address for vDSO\n");
}
printf("=> vDSO base address: %pS\n", vdso);
// Basic assertion :)
- ensure_proper_elf_header((const char *) vdso);
+ ensure_proper_elf_header((const char *)vdso);
// The ELF header is the first thing starting from the fetched address.
- const Elf64_Ehdr *ehdr = (const Elf64_Ehdr *) vdso;
+ const Elf64_Ehdr *ehdr = (const Elf64_Ehdr *)vdso;
/*
* Grab the base address for the Section Header Table for the ELF
@@ -81,56 +75,57 @@ int main(void)
* dynamic symbol table and the dynamic string table. This will be used
* later for looking up the address for each given function name.
*/
- const Elf64_Shdr *shdr = (const Elf64_Shdr *)((const char *) vdso + ehdr->e_shoff);
- const Elf64_Shdr *symbols_header = NULL;
- const Elf64_Shdr *strings_header = NULL;
-
- for (int i = 0; i < ehdr->e_shnum; i++) {
- if (shdr[i].sh_type == SHT_DYNSYM) {
- symbols_header = &shdr[i];
- } else if (shdr[i].sh_type == SHT_STRTAB) {
- const char *shstrtab = (const char *) vdso + shdr[ehdr->e_shstrndx].sh_offset;
- const char *strtab_name = shstrtab + shdr[i].sh_name;
-
- if (strcmp(strtab_name, ".dynstr") == 0) {
- strings_header = &shdr[i];
- }
- }
- }
- if (!symbols_header || !strings_header) {
- die("Could not find .dynsym or .dynstr sections\n");
- }
+ const Elf64_Shdr *shdr = (const Elf64_Shdr *)((const char *)vdso + ehdr->e_shoff);
+ const Elf64_Shdr *symbols_header = NULL;
+ const Elf64_Shdr *strings_header = NULL;
+
+ for (int i = 0; i < ehdr->e_shnum; i++) {
+ if (shdr[i].sh_type == SHT_DYNSYM) {
+ symbols_header = &shdr[i];
+ } else if (shdr[i].sh_type == SHT_STRTAB) {
+ const char *shstrtab = (const char *)vdso + shdr[ehdr->e_shstrndx].sh_offset;
+ const char *strtab_name = shstrtab + shdr[i].sh_name;
+
+ if (strcmp(strtab_name, ".dynstr") == 0) {
+ strings_header = &shdr[i];
+ }
+ }
+ }
+ if (!symbols_header || !strings_header) {
+ die("Could not find .dynsym or .dynstr sections\n");
+ }
/*
* Now that we know where to pick the strings and their corresponding
* addresses, let's use their offsets to pair it with the original base
* 'vdso' address. This will give us a pointer to the proper tables.
*/
- const Elf64_Sym *symbols_table = (const Elf64_Sym *)((const char *) vdso + symbols_header->sh_offset);
- const char *strings_table = (const char *)((const char *) vdso + strings_header->sh_offset);
- int num_symbols = symbols_header->sh_size / symbols_header->sh_entsize;
+ const Elf64_Sym *symbols_table =
+ (const Elf64_Sym *)((const char *)vdso + symbols_header->sh_offset);
+ const char *strings_table = (const char *)((const char *)vdso + strings_header->sh_offset);
+ int num_symbols = symbols_header->sh_size / symbols_header->sh_entsize;
/*
* As an example we will find the 'getcpu' system call which is exported on
* a Linux x86_64 system.
*/
- int (*vdso_getcpu)(unsigned int *, unsigned int*) = NULL;
+ int (*vdso_getcpu)(unsigned int *, unsigned int *) = NULL;
printf("=> The following system calls are available via vDSO:\n");
- for (int i = 0; i < num_symbols; i++) {
+ for (int i = 0; i < num_symbols; i++) {
// The name of the function directly sits at the strings table plus the
// offset given on the symbols table.
- const char *name = strings_table + symbols_table[i].st_name;
+ const char *name = strings_table + symbols_table[i].st_name;
if (is_vdso_function(name)) {
- void *address = (void *)((char *) vdso + symbols_table[i].st_value);
+ void *address = (void *)((char *)vdso + symbols_table[i].st_value);
printf("\t%s (address: %p)\n", name, address);
if (strcmp(name, "__vdso_getcpu") == 0) {
- vdso_getcpu = (int (*)(unsigned int *, unsigned int *)) address;
+ vdso_getcpu = (int (*)(unsigned int *, unsigned int *))address;
}
}
- }
+ }
/*
* As an example, run the 'getcpu' system call via the vDSO mechanism.