Home | History | Annotate | Download | only in daemon
      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