blob: 3578e4829d60e0ee1bb8a75558a139699ebcf708 [file] [log] [blame]
/**
* @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]);
}