/** * @file opd_cookie.c * cookie -> name cache * * @remark Copyright 2002, 2005 OProfile authors * @remark Read the file COPYING * * @author John Levon */ #include "opd_cookie.h" #include "oprofiled.h" #include "op_list.h" #include "op_libiberty.h" #include <sys/syscall.h> #include <unistd.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #ifndef __NR_lookup_dcookie #if defined(__i386__) #define __NR_lookup_dcookie 253 #elif defined(__x86_64__) #define __NR_lookup_dcookie 212 #elif defined(__powerpc__) #define __NR_lookup_dcookie 235 #elif defined(__alpha__) #define __NR_lookup_dcookie 406 #elif defined(__hppa__) #define __NR_lookup_dcookie 223 #elif defined(__ia64__) #define __NR_lookup_dcookie 1237 #elif defined(__sparc__) /* untested */ #define __NR_lookup_dcookie 208 #elif defined(__s390__) || defined (__s390x__) #define __NR_lookup_dcookie 110 #elif defined(__arm__) #define __NR_lookup_dcookie (__NR_SYSCALL_BASE+249) #elif defined(__mips__) #include <sgidefs.h> /* O32 */ #if _MIPS_SIM == _MIPS_SIM_ABI32 #define __NR_lookup_dcookie 4247 /* N64 */ #elif _MIPS_SIM == _MIPS_SIM_ABI64 #define __NR_lookup_dcookie 5206 /* N32 */ #elif _MIPS_SIM == _MIPS_SIM_NABI32 #define __NR_lookup_dcookie 6206 #else #error Unknown MIPS ABI: Dunno __NR_lookup_dcookie #endif #else #error Please define __NR_lookup_dcookie for your architecture #endif #endif /* __NR_lookup_dcookie */ #if (defined(__powerpc__) && !defined(__powerpc64__)) || defined(__hppa__)\ || (defined(__s390__) && !defined(__s390x__)) \ || (defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32) \ && defined(__MIPSEB__)) \ || (defined(__arm__) && defined(__ARM_EABI__) \ && defined(__ARMEB__)) static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) { return syscall(__NR_lookup_dcookie, (unsigned long)(cookie >> 32), (unsigned long)(cookie & 0xffffffff), buf, size); } #elif (defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32)) \ || (defined(__arm__) && defined(__ARM_EABI__)) static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) { return syscall(__NR_lookup_dcookie, (unsigned long)(cookie & 0xffffffff), (unsigned long)(cookie >> 32), buf, size); } #else static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) { return syscall(__NR_lookup_dcookie, cookie, buf, size); } #endif struct cookie_entry { cookie_t value; char * name; int ignored; struct list_head list; }; #define HASH_SIZE 512 #define HASH_BITS (HASH_SIZE - 1) static struct list_head hashes[HASH_SIZE]; static struct cookie_entry * create_cookie(cookie_t cookie) { int err; struct cookie_entry * entry = xmalloc(sizeof(struct cookie_entry)); entry->value = cookie; entry->name = xmalloc(PATH_MAX + 1); err = lookup_dcookie(cookie, entry->name, PATH_MAX); if (err < 0) { fprintf(stderr, "Lookup of cookie %llx failed, errno=%d\n", cookie, errno); free(entry->name); entry->name = NULL; entry->ignored = 0; } else { entry->ignored = is_image_ignored(entry->name); } return entry; } /* Cookie monster want cookie! */ static unsigned long hash_cookie(cookie_t cookie) { return (cookie >> DCOOKIE_SHIFT) & (HASH_SIZE - 1); } char const * find_cookie(cookie_t cookie) { unsigned long hash = hash_cookie(cookie); struct list_head * pos; struct cookie_entry * entry; if (cookie == INVALID_COOKIE || cookie == NO_COOKIE) return NULL; list_for_each(pos, &hashes[hash]) { entry = list_entry(pos, struct cookie_entry, list); if (entry->value == cookie) goto out; } /* not sure this can ever happen due to is_cookie_ignored */ entry = create_cookie(cookie); list_add(&entry->list, &hashes[hash]); out: return entry->name; } int is_cookie_ignored(cookie_t cookie) { unsigned long hash = hash_cookie(cookie); struct list_head * pos; struct cookie_entry * entry; if (cookie == INVALID_COOKIE || cookie == NO_COOKIE) return 1; list_for_each(pos, &hashes[hash]) { entry = list_entry(pos, struct cookie_entry, list); if (entry->value == cookie) goto out; } entry = create_cookie(cookie); list_add(&entry->list, &hashes[hash]); out: return entry->ignored; } char const * verbose_cookie(cookie_t cookie) { unsigned long hash = hash_cookie(cookie); struct list_head * pos; struct cookie_entry * entry; if (cookie == INVALID_COOKIE) return "invalid"; if (cookie == NO_COOKIE) return "anonymous"; list_for_each(pos, &hashes[hash]) { entry = list_entry(pos, struct cookie_entry, list); if (entry->value == cookie) { if (!entry->name) return "failed lookup"; return entry->name; } } return "not hashed"; } void cookie_init(void) { size_t i; for (i = 0; i < HASH_SIZE; ++i) list_init(&hashes[i]); }