-
Notifications
You must be signed in to change notification settings - Fork 130
/
vdso.c
122 lines (97 loc) · 3.53 KB
/
vdso.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
///////////////////////////////////////////////////////////////////////////////
// vdso.c - 2023
//
/// This module contains code to dump the vDSO symbol table
///
/// @file vdso.c
/// @author Mark Nelson <[email protected]>
/// @author Brooke Maeda <[email protected]>
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h> // For printf()
#include <sys/auxv.h> // For getauxval
#include <stdbool.h> // For bool true false
#include "vdso.h" // For obvious reasons
/// Get the vDSO dynamic link table `PT_DYNAMIC`
///
/// Iterate over `phdrtab` until it finds the `PT_DYNAMIC` entry
///
/// @param addr vDSO base address
/// @return A pointer to the table or `NULL` if it's not found
static Elf64_Dyn* vdso_get_dynamic_link_table( void* addr ) {
Elf64_Ehdr* ehdr = addr;
Elf64_Phdr* phdrtab = (Elf64_Phdr*)((char*)addr + ehdr->e_phoff);
for( int i = 0 ; i < ehdr->e_phnum ; i++ ) {
if( phdrtab[i].p_type == PT_DYNAMIC ) {
// return (Elf64_Dyn*)addr + phdrtab[i].p_offset;
return (Elf64_Dyn*)((char*)addr + phdrtab[i].p_offset);
}
}
return NULL;
}
/// Get a dynamic section from a vDSO file
///
/// @param addr vDSO base address
/// @param dyntab Pointer to a vDSO dynamic link table
/// @param tag A dynamic section type. eg. `DT_HASH`, `DT_STRTAB`, et.al.
/// @return A pointer to a dynamic vDSO section or `NULL` if it's not found
static void* vdso_get_dynamic_section( void* addr, Elf64_Dyn* dyntab, Elf64_Sxword tag ) {
for( int i = 0 ; dyntab[i].d_tag != DT_NULL ; i++ ) {
if( dyntab[i].d_tag == tag ) {
// return (Elf64_Phdr*)addr + dyntab[i].d_un.d_ptr;
return (char*)addr + dyntab[i].d_un.d_ptr;
}
}
return NULL;
}
/// Get the symbol table from the vDSO
///
/// @param addr vDSO base address
/// @param symtab A pointer to a symbol table structure which gets populated
/// by this function.
/// @return `true` if successful. `false` if not.
static bool vdso_get_symbol_table( void* addr, struct vdso_symtab* symtab ) {
Elf64_Dyn* dyntab = vdso_get_dynamic_link_table( addr );
symtab->elf_symtab = vdso_get_dynamic_section( addr, dyntab, DT_SYMTAB );
if( !symtab->elf_symtab )
return false;
symtab->elf_symstrtab = vdso_get_dynamic_section( addr, dyntab, DT_STRTAB );
if( !symtab->elf_symstrtab )
return false;
symtab->elf_hashtab = vdso_get_dynamic_section( addr, dyntab, DT_HASH );
if( !symtab->elf_hashtab )
return false;
return true;
}
/// Print the symbol table pointed to by `symtab`
///
/// @param symtab Pointer to a vDSO symbol table
void print_whole_symbol_table( struct vdso_symtab* symtab ) {
Elf64_Word bucketnum = symtab->elf_hashtab[0];
Elf64_Word* buckettab = &symtab->elf_hashtab[2];
Elf64_Word* chaintab = &symtab->elf_hashtab[2 + bucketnum];
Elf64_Sym* sym;
for( Elf64_Word i = 0 ; i < bucketnum ; ++i ) {
for( Elf64_Word j = buckettab[i] ; j != STN_UNDEF ; j = chaintab[j]) {
sym = &symtab->elf_symtab[j];
printf( "vDSO symbol: %s\n", &symtab->elf_symstrtab[sym->st_name] );
}
}
}
/// Print out the vDSO symbol table
void dump_vDSO ( void ) {
struct vdso_symtab symtab;
// Get vDSO base address
void* vdso_base_addr;
vdso_base_addr = (void *)getauxval( AT_SYSINFO_EHDR );
if( !vdso_base_addr ) {
printf( "Can't get vDSO base address\n" );
return;
}
printf( "vDSO base address: %p\n", vdso_base_addr );
if( !vdso_get_symbol_table( vdso_base_addr, &symtab ) ){
printf( "Can't get a symbol table from the vDSO\n" );
return;
}
printf( "Printing Symbol Table:\n" );
print_whole_symbol_table( &symtab );
}