1/* Test dwfl_linux_proc_attach works without any modules. 2 Copyright (C) 2015 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 <inttypes.h> 20#include <stdio.h> 21#include <stdlib.h> 22#include <errno.h> 23#include <unistd.h> 24#ifdef __linux__ 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <sys/user.h> 28#include <fcntl.h> 29#include <string.h> 30#include ELFUTILS_HEADER(dwfl) 31#include <pthread.h> 32#endif 33#include "system.h" 34 35#ifndef __linux__ 36int 37main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused))) 38{ 39 printf ("dwfl_linux_proc_attach unsupported.\n"); 40 return 77; 41} 42#else /* __linux__ */ 43 44static pthread_t thread1; 45static pthread_t thread2; 46 47static void * 48sleeper (void* d __attribute__ ((unused))) 49{ 50 sleep (60); 51 return NULL; 52} 53 54static char *debuginfo_path = NULL; 55 56static const Dwfl_Callbacks proc_callbacks = 57 { 58 .find_elf = dwfl_linux_proc_find_elf, 59 .find_debuginfo = dwfl_standard_find_debuginfo, 60 .debuginfo_path = &debuginfo_path, 61 }; 62 63static int 64thread_callback (Dwfl_Thread *thread, void *thread_arg) 65{ 66 int *threads = (int *) thread_arg; 67 pid_t tid = dwfl_thread_tid (thread); 68 printf ("thread tid: %d\n", tid); 69 (*threads)++; 70 71 return DWARF_CB_OK; 72} 73 74int 75main (int argc __attribute__ ((unused)), 76 char **argv __attribute__ ((unused))) 77{ 78 /* Create two extra threads to iterate through. */ 79 int err; 80 if ((err = pthread_create (&thread1, NULL, sleeper, NULL)) != 0) 81 error (-1, err, "Couldn't create thread1"); 82 if ((err = pthread_create (&thread2, NULL, sleeper, NULL)) != 0) 83 error (-1, err, "Couldn't create thread2"); 84 85 Dwfl *dwfl = dwfl_begin (&proc_callbacks); 86 if (dwfl == NULL) 87 error (-1, 0, "dwfl_begin: %s", dwfl_errmsg (-1)); 88 89 pid_t pid = getpid (); 90 /* This used to fail, since we don't have any modules yet. */ 91 if (dwfl_linux_proc_attach (dwfl, pid, false) < 0) 92 error (-1, 0, "dwfl_linux_proc_attach pid %d: %s", pid, 93 dwfl_errmsg (-1)); 94 95 /* Did we see all 3 threads? */ 96 int threads = 0; 97 if (dwfl_getthreads (dwfl, thread_callback, &threads) != DWARF_CB_OK) 98 error (-1, 0, "dwfl_getthreads failed: %s", dwfl_errmsg (-1)); 99 100 dwfl_end (dwfl); 101 102 pthread_cancel (thread1); 103 pthread_cancel (thread2); 104 pthread_join (thread1, NULL); 105 pthread_join (thread2, NULL); 106 107 return (threads == 3) ? 0 : -1; 108} 109 110/* HACK. This is a simple workaround for a combination of old glibc 111 and valgrind. libdw will try to dlopen libdebuginfod this causes 112 some unsuppressable memory leak warnings when the process is 113 multi-threaded under valgrind because of some bad backtraces. 114 So simply override dlopen and always return NULL so libdebuginfod 115 (and libcurl) are never loaded. This test doesn't rely on 116 libdebuginfod anyway. */ 117void *dlopen (void) 118{ 119 return NULL; 120} 121 122#endif /* __linux__ */ 123