1 /** 2 * @file opd_cookie.c 3 * cookie -> name cache 4 * 5 * @remark Copyright 2002, 2005 OProfile authors 6 * @remark Read the file COPYING 7 * 8 * @author John Levon 9 */ 10 11 #include "opd_cookie.h" 12 #include "oprofiled.h" 13 #include "op_list.h" 14 #include "op_libiberty.h" 15 16 #include <sys/syscall.h> 17 #include <unistd.h> 18 #include <limits.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <errno.h> 22 23 #ifndef __NR_lookup_dcookie 24 #if defined(__i386__) 25 #define __NR_lookup_dcookie 253 26 #elif defined(__x86_64__) 27 #define __NR_lookup_dcookie 212 28 #elif defined(__powerpc__) 29 #define __NR_lookup_dcookie 235 30 #elif defined(__alpha__) 31 #define __NR_lookup_dcookie 406 32 #elif defined(__hppa__) 33 #define __NR_lookup_dcookie 223 34 #elif defined(__ia64__) 35 #define __NR_lookup_dcookie 1237 36 #elif defined(__sparc__) 37 /* untested */ 38 #define __NR_lookup_dcookie 208 39 #elif defined(__s390__) || defined (__s390x__) 40 #define __NR_lookup_dcookie 110 41 #elif defined(__arm__) 42 #define __NR_lookup_dcookie (__NR_SYSCALL_BASE+249) 43 #elif defined(__mips__) 44 #include <sgidefs.h> 45 /* O32 */ 46 #if _MIPS_SIM == _MIPS_SIM_ABI32 47 #define __NR_lookup_dcookie 4247 48 /* N64 */ 49 #elif _MIPS_SIM == _MIPS_SIM_ABI64 50 #define __NR_lookup_dcookie 5206 51 /* N32 */ 52 #elif _MIPS_SIM == _MIPS_SIM_NABI32 53 #define __NR_lookup_dcookie 6206 54 #else 55 #error Unknown MIPS ABI: Dunno __NR_lookup_dcookie 56 #endif 57 #else 58 #error Please define __NR_lookup_dcookie for your architecture 59 #endif 60 #endif /* __NR_lookup_dcookie */ 61 62 #if (defined(__powerpc__) && !defined(__powerpc64__)) || defined(__hppa__)\ 63 || (defined(__s390__) && !defined(__s390x__)) \ 64 || (defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32) \ 65 && defined(__MIPSEB__)) \ 66 || (defined(__arm__) && defined(__ARM_EABI__) \ 67 && defined(__ARMEB__)) 68 static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) 69 { 70 return syscall(__NR_lookup_dcookie, (unsigned long)(cookie >> 32), 71 (unsigned long)(cookie & 0xffffffff), buf, size); 72 } 73 #elif (defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32)) \ 74 || (defined(__arm__) && defined(__ARM_EABI__)) 75 static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) 76 { 77 return syscall(__NR_lookup_dcookie, 78 (unsigned long)(cookie & 0xffffffff), 79 (unsigned long)(cookie >> 32), buf, size); 80 } 81 #else 82 static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) 83 { 84 return syscall(__NR_lookup_dcookie, cookie, buf, size); 85 } 86 #endif 87 88 89 struct cookie_entry { 90 cookie_t value; 91 char * name; 92 int ignored; 93 struct list_head list; 94 }; 95 96 97 #define HASH_SIZE 512 98 #define HASH_BITS (HASH_SIZE - 1) 99 100 static struct list_head hashes[HASH_SIZE]; 101 102 static struct cookie_entry * create_cookie(cookie_t cookie) 103 { 104 int err; 105 struct cookie_entry * entry = xmalloc(sizeof(struct cookie_entry)); 106 107 entry->value = cookie; 108 entry->name = xmalloc(PATH_MAX + 1); 109 110 err = lookup_dcookie(cookie, entry->name, PATH_MAX); 111 112 if (err < 0) { 113 fprintf(stderr, "Lookup of cookie %llx failed, errno=%d\n", 114 cookie, errno); 115 free(entry->name); 116 entry->name = NULL; 117 entry->ignored = 0; 118 } else { 119 entry->ignored = is_image_ignored(entry->name); 120 } 121 122 return entry; 123 } 124 125 126 /* Cookie monster want cookie! */ 127 static unsigned long hash_cookie(cookie_t cookie) 128 { 129 return (cookie >> DCOOKIE_SHIFT) & (HASH_SIZE - 1); 130 } 131 132 133 char const * find_cookie(cookie_t cookie) 134 { 135 unsigned long hash = hash_cookie(cookie); 136 struct list_head * pos; 137 struct cookie_entry * entry; 138 139 if (cookie == INVALID_COOKIE || cookie == NO_COOKIE) 140 return NULL; 141 142 list_for_each(pos, &hashes[hash]) { 143 entry = list_entry(pos, struct cookie_entry, list); 144 if (entry->value == cookie) 145 goto out; 146 } 147 148 /* not sure this can ever happen due to is_cookie_ignored */ 149 entry = create_cookie(cookie); 150 list_add(&entry->list, &hashes[hash]); 151 out: 152 return entry->name; 153 } 154 155 156 int is_cookie_ignored(cookie_t cookie) 157 { 158 unsigned long hash = hash_cookie(cookie); 159 struct list_head * pos; 160 struct cookie_entry * entry; 161 162 if (cookie == INVALID_COOKIE || cookie == NO_COOKIE) 163 return 1; 164 165 list_for_each(pos, &hashes[hash]) { 166 entry = list_entry(pos, struct cookie_entry, list); 167 if (entry->value == cookie) 168 goto out; 169 } 170 171 entry = create_cookie(cookie); 172 list_add(&entry->list, &hashes[hash]); 173 out: 174 return entry->ignored; 175 } 176 177 178 char const * verbose_cookie(cookie_t cookie) 179 { 180 unsigned long hash = hash_cookie(cookie); 181 struct list_head * pos; 182 struct cookie_entry * entry; 183 184 if (cookie == INVALID_COOKIE) 185 return "invalid"; 186 187 if (cookie == NO_COOKIE) 188 return "anonymous"; 189 190 list_for_each(pos, &hashes[hash]) { 191 entry = list_entry(pos, struct cookie_entry, list); 192 if (entry->value == cookie) { 193 if (!entry->name) 194 return "failed lookup"; 195 return entry->name; 196 } 197 } 198 199 return "not hashed"; 200 } 201 202 203 void cookie_init(void) 204 { 205 size_t i; 206 207 for (i = 0; i < HASH_SIZE; ++i) 208 list_init(&hashes[i]); 209 } 210