1 /* Test program for getting symbol table from vdso module. 2 Copyright (C) 2014 Red Hat, Inc. 3 This file is part of elfutils. 4 5 This file is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18 #include <config.h> 19 #include <assert.h> 20 #include <errno.h> 21 #include <error.h> 22 #include <inttypes.h> 23 #include <stdio.h> 24 #include <string.h> 25 #include <sys/types.h> 26 #include <unistd.h> 27 #include ELFUTILS_HEADER(dwfl) 28 29 #ifndef __linux__ 30 int 31 main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused))) 32 { 33 printf ("Getting the vdso is unsupported.\n"); 34 return 77; 35 } 36 #else /* __linux__ */ 37 static int vdso_syms = 0; 38 39 static int 40 module_callback (Dwfl_Module *mod, void **userdata __attribute__((unused)), 41 const char *name, Dwarf_Addr start __attribute__((unused)), 42 void *arg __attribute__((unused))) 43 { 44 /* We can only recognize the vdso by inspecting the "magic name". */ 45 printf ("module name: %s\n", name); 46 if (strncmp ("[vdso: ", name, 7) == 0) 47 { 48 vdso_syms = dwfl_module_getsymtab (mod); 49 printf ("vdso syms: %d\n", vdso_syms); 50 if (vdso_syms < 0) 51 error (2, 0, "dwfl_module_getsymtab: %s", dwfl_errmsg (-1)); 52 53 for (int i = 0; i < vdso_syms; i++) 54 { 55 GElf_Sym sym; 56 GElf_Addr addr; 57 const char *sname = dwfl_module_getsym_info (mod, i, &sym, &addr, 58 NULL, NULL, NULL); 59 assert (sname != NULL); 60 printf ("%d: '%s' %" PRIx64 " (%" PRIx64 ")\n", 61 i, sname, sym.st_value, addr); 62 } 63 } 64 65 return DWARF_CB_OK; 66 } 67 68 int 69 main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused))) 70 { 71 static char *debuginfo_path; 72 static const Dwfl_Callbacks proc_callbacks = 73 { 74 .find_debuginfo = dwfl_standard_find_debuginfo, 75 .debuginfo_path = &debuginfo_path, 76 77 .find_elf = dwfl_linux_proc_find_elf, 78 }; 79 Dwfl *dwfl = dwfl_begin (&proc_callbacks); 80 if (dwfl == NULL) 81 error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1)); 82 83 /* Take ourself as "arbitrary" process to inspect. This should work 84 even with "restricted ptrace". */ 85 pid_t pid = getpid(); 86 87 int result = dwfl_linux_proc_report (dwfl, pid); 88 if (result < 0) 89 error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1)); 90 else if (result > 0) 91 error (2, result, "dwfl_linux_proc_report"); 92 93 /* Also explicitly attach for older kernels (cannot read vdso otherwise). */ 94 result = dwfl_linux_proc_attach (dwfl, pid, false); 95 if (result < 0) 96 error (2, 0, "dwfl_linux_proc_attach: %s", dwfl_errmsg (-1)); 97 else if (result > 0) 98 error (2, result, "dwfl_linux_proc_attach"); 99 100 if (dwfl_report_end (dwfl, NULL, NULL) != 0) 101 error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1)); 102 103 if (dwfl_getmodules (dwfl, module_callback, NULL, 0) != 0) 104 error (1, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); 105 106 /* No symbols is ok, then we haven't seen the vdso at all on this arch. */ 107 return vdso_syms >= 0 ? 0 : -1; 108 } 109 110 #endif /* ! __linux__ */ 111