From: John L. <le...@mo...> - 2003-01-09 02:16:37
|
This is a step forward even if there's some niggles. It's untested so it would be good if people could try it out with latest CVS, especially on 64-bit or 64/32 machines :) Note that we're still storing only unsigned longs in the hash table, but as this is an offset I think it should be ok. The post-profile userspace should hopefully be OK now (maybe some little bits left) comments ? regards john ? oprofile-0.5cvs.tar.gz Index: daemon/opd_image.c =================================================================== RCS file: /cvsroot/oprofile/oprofile/daemon/opd_image.c,v retrieving revision 1.21 diff -u -r1.21 opd_image.c --- daemon/opd_image.c 10 Dec 2002 14:36:59 -0000 1.21 +++ daemon/opd_image.c 9 Jan 2003 02:07:10 -0000 @@ -30,6 +30,7 @@ extern uint op_nr_counters; extern int separate_samples; +extern size_t kernel_pointer_size; /* maintained for statistics purpose only */ unsigned int nr_images=0; @@ -131,7 +132,7 @@ return image; } -static int lookup_dcookie(u_int64_t cookie, char * buf, size_t size) +static int lookup_dcookie(cookie_t cookie, char * buf, size_t size) { // FIXME return syscall(253, cookie, buf, size); @@ -141,15 +142,15 @@ /** * opd_init_image - init an image sample file */ -static void opd_init_image(struct opd_image * image, unsigned long cookie, - unsigned long app_cookie) +static void opd_init_image(struct opd_image * image, cookie_t cookie, + cookie_t app_cookie) { char buf[PATH_MAX + 1]; /* FIXME: if dcookie lookup fail we will re open multiple time the * same db which doesn't work */ if (lookup_dcookie(cookie, buf, PATH_MAX) <= 0) { - printf("Lookup of cookie %lu failed, errno=%d\n", + printf("Lookup of cookie %Lx failed, errno=%d\n", cookie, errno); image->name = xstrdup(""); } else { @@ -157,7 +158,7 @@ } if (lookup_dcookie(app_cookie, buf, PATH_MAX) <= 0) { - printf("Lookup of cookie %lu failed, errno=%d\n", + printf("Lookup of cookie %Lx failed, errno=%d\n", cookie, errno); image->app_name = xstrdup(""); } else { @@ -245,7 +246,7 @@ * count is the raw value passed from the kernel. */ void opd_put_image_sample(struct opd_image * image, - unsigned long offset, int counter) + vma_t offset, int counter) { samples_db_t * sample_file; @@ -259,12 +260,13 @@ } } - db_insert(sample_file, offset, 1); + /* Possible narrowing to 32-bit value only. */ + db_insert(sample_file, (unsigned long)offset, 1); } /** return hash value for a cookie */ -static unsigned long opd_hash_cookie(unsigned long cookie) +static unsigned long opd_hash_cookie(cookie_t cookie) { return (cookie >> DCOOKIE_SHIFT) & (IMAGE_HASH_SIZE - 1); } @@ -273,7 +275,7 @@ /** * opd_add_image - add an image to the image hashlist */ -static struct opd_image * opd_add_image(unsigned long cookie, unsigned long app_cookie) +static struct opd_image * opd_add_image(cookie_t cookie, cookie_t app_cookie) { unsigned long hash = opd_hash_cookie(cookie); struct opd_image * image = opd_create_image(hash); @@ -288,7 +290,7 @@ /** * opd_find_image - find an image */ -static struct opd_image * opd_find_image(unsigned long cookie, unsigned long app_cookie) +static struct opd_image * opd_find_image(cookie_t cookie, cookie_t app_cookie) { unsigned long hash = opd_hash_cookie(cookie); struct opd_image * image = 0; @@ -313,7 +315,7 @@ /** * opd_get_image - get an image from the image structure */ -static struct opd_image * opd_get_image(unsigned long cookie, unsigned long app_cookie) +static struct opd_image * opd_get_image(cookie_t cookie, cookie_t app_cookie) { struct opd_image * image; if ((image = opd_find_image(cookie, app_cookie)) == NULL) @@ -350,22 +352,36 @@ } -static void opd_put_sample(struct opd_image * image, unsigned long const * data) +static u_int64_t get_buffer_value(void const * buffer, size_t index) { - unsigned long eip = data[0]; - unsigned long event = data[1]; + if (kernel_pointer_size == 4) { + u_int32_t const * lbuf = buffer; + return lbuf[index]; + } else { + u_int64_t const * lbuf = buffer; + return lbuf[index]; + } +} + + +static void opd_put_sample(struct opd_image * image, char const * buffer, size_t index) +{ + vma_t eip = get_buffer_value(buffer, index); + unsigned long event = get_buffer_value(buffer, index + 1); if (opd_eip_is_kernel(eip)) { - verbprintf("Kernel sample 0x%lx, counter %lu\n", eip, event); + verbprintf("Kernel sample 0x%Lx, counter %Lu\n", + (u_int64_t)eip, (u_int64_t)event); opd_handle_kernel_sample(eip, event); } else { - verbprintf("Image (%s) offset 0x%lx, counter %lu\n", image->name, eip, event); + verbprintf("Image (%s) offset 0x%Lx, counter %Lu\n", + image->name, (u_int64_t)eip, (u_int64_t)event); opd_put_image_sample(image, eip, event); } } -void complete_dump() +static void complete_dump() { FILE *status_file; @@ -381,19 +397,20 @@ // FIXME: pid/pgrp filter ? -void opd_process_samples(unsigned long const * buffer, size_t count) +void opd_process_samples(char const * buffer, size_t count) { unsigned long i = 0; unsigned long cpu = 0; - unsigned long code, pid, cookie, app_cookie = 0; + unsigned long code, pid; + cookie_t cookie, app_cookie = 0; struct opd_image * image = NULL; while (i < count) { - if (buffer[i] != ESCAPE_CODE) { + if (get_buffer_value(buffer, i) != ESCAPE_CODE) { if (i + 1 == count) return; - opd_put_sample(image, &buffer[i]); + opd_put_sample(image, buffer, i); i += 2; continue; } @@ -402,7 +419,7 @@ if (++i == count) return; - code = buffer[i]; + code = get_buffer_value(buffer, i); // skip code if (++i == count) @@ -410,27 +427,29 @@ switch (code) { case CPU_SWITCH_CODE: - cpu = buffer[i]; + cpu = get_buffer_value(buffer, i); verbprintf("CPU_SWITCH to %lu\n", cpu); ++i; break; case COOKIE_SWITCH_CODE: - cookie = buffer[i]; + cookie = get_buffer_value(buffer, i); image = opd_get_image(cookie, app_cookie); - verbprintf("COOKIE_SWITCH to cookie %lu (%s)\n", cookie, image->name); + verbprintf("COOKIE_SWITCH to cookie %Lx (%s)\n", cookie, image->name); ++i; break; case CTX_SWITCH_CODE: - pid = buffer[i]; + pid = get_buffer_value(buffer, i); // skip pid if (++i == count) break; - app_cookie = buffer[i]; + app_cookie = get_buffer_value(buffer, i); ++i; break; } } + + // FIXME: this should be done by the caller I think complete_dump(); } Index: daemon/opd_image.h =================================================================== RCS file: /cvsroot/oprofile/oprofile/daemon/opd_image.h,v retrieving revision 1.7 diff -u -r1.7 opd_image.h --- daemon/opd_image.h 3 Dec 2002 02:53:21 -0000 1.7 +++ daemon/opd_image.h 9 Jan 2003 02:07:12 -0000 @@ -29,9 +29,9 @@ /* name of the owning app or "" */ char * app_name; /* cookie value for this image if any */ - unsigned long cookie; + cookie_t cookie; /* cookie value of the owning app or 0 */ - unsigned long app_cookie; + cookie_t app_cookie; /* hash table link */ struct list_head hash_list; /* opened sample files */ @@ -45,7 +45,7 @@ typedef void (*opd_image_cb)(struct opd_image *); void opd_for_each_image(opd_image_cb imagecb); -void opd_put_image_sample(struct opd_image * image, unsigned long offset, int counter); +void opd_put_image_sample(struct opd_image * image, vma_t offset, int counter); void opd_image_cleanup(void); @@ -55,6 +55,6 @@ struct op_sample; -void opd_process_samples(unsigned long const * buffer, size_t count); +void opd_process_samples(char const * buffer, size_t count); #endif /* OPD_IMAGE_H */ Index: daemon/opd_kernel.c =================================================================== RCS file: /cvsroot/oprofile/oprofile/daemon/opd_kernel.c,v retrieving revision 1.7 diff -u -r1.7 opd_kernel.c --- daemon/opd_kernel.c 3 Dec 2002 03:44:50 -0000 1.7 +++ daemon/opd_kernel.c 9 Jan 2003 02:07:15 -0000 @@ -27,8 +27,8 @@ struct opd_module { char * name; struct opd_image * image; - unsigned long start; - unsigned long end; + vma_t start; + vma_t end; }; extern char * vmlinux; @@ -38,8 +38,8 @@ static struct opd_image * kernel_image; /* kernel and module support */ -static unsigned long kernel_start; -static unsigned long kernel_end; +static vma_t kernel_start; +static vma_t kernel_end; static struct opd_module opd_modules[OPD_MAX_MODULES]; static unsigned int nr_modules=0; @@ -56,14 +56,14 @@ */ void opd_parse_kernel_range(char const * arg) { - sscanf(arg, "%lx,%lx", &kernel_start, &kernel_end); + sscanf(arg, "%Lx,%Lx", &kernel_start, &kernel_end); - verbprintf("OPD_PARSE_KERNEL_RANGE: kernel_start = %lx, kernel_end = %lx\n", + verbprintf("OPD_PARSE_KERNEL_RANGE: kernel_start = %Lx, kernel_end = %Lx\n", kernel_start, kernel_end); if (kernel_start == 0x0 || kernel_end == 0x0) { fprintf(stderr, - "Warning: mis-parsed kernel range: %lx-%lx\n", + "Warning: mis-parsed kernel range: %Lx-%Lx\n", kernel_start, kernel_end); fprintf(stderr, "kernel profiles will be wrong.\n"); } @@ -95,7 +95,7 @@ * @param end end address */ static struct opd_module * new_module(char * name, - unsigned long start, unsigned long end) + vma_t start, vma_t end) { opd_modules[nr_modules].name = name; opd_modules[nr_modules].image = NULL; @@ -184,14 +184,14 @@ goto failure; } - if (strncmp("__insmod_", line+9, 9)) { + if (strncmp("__insmod_", line + 9, 9)) { free(line); continue; } cp = line + 18; cp2 = cp; - while ((*cp2) && !!strncmp("_S", cp2+1, 2) && !!strncmp("_O", cp2+1, 2)) + while ((*cp2) && !!strncmp("_S", cp2 + 1, 2) && !!strncmp("_O", cp2 + 1, 2)) cp2++; if (!*cp2) { @@ -201,8 +201,8 @@ cp2++; /* freed by opd_clear_module_info() or opd_get_module() */ - modname = xmalloc((size_t)((cp2-cp) + 1)); - strncpy(modname, cp, (size_t)((cp2-cp))); + modname = xmalloc((size_t)((cp2 - cp) + 1)); + strncpy(modname, cp, (size_t)((cp2 - cp))); modname[cp2-cp] = '\0'; mod = opd_get_module(modname); @@ -213,7 +213,7 @@ cp2++; cp3 = cp2; - while ((*cp3) && !!strncmp("_M", cp3+1, 2)) + while ((*cp3) && !!strncmp("_M", cp3 + 1, 2)) cp3++; if (!*cp3) { @@ -239,8 +239,8 @@ } cp2 += 7; - sscanf(line,"%lx", &mod->start); - sscanf(cp2,"%lu", &mod->end); + sscanf(line,"%Lx", &mod->start); + sscanf(cp2,"%Lu", &mod->end); mod->end += mod->start; break; } @@ -258,7 +258,7 @@ * opd_drop_module_sample - drop a module sample efficiently * @param eip eip of sample */ -static void opd_drop_module_sample(unsigned long eip) +static void opd_drop_module_sample(vma_t eip) { char * module_names; char * name; @@ -306,7 +306,7 @@ * contain this eip return %NULL if not found. * caller must check than the module image is valid */ -static struct opd_module * opd_find_module_by_eip(unsigned long eip) +static struct opd_module * opd_find_module_by_eip(vma_t eip) { uint i; for (i = 0; i < nr_modules; i++) { @@ -335,7 +335,7 @@ * If the sample could not be located in a module, it is treated * as a kernel sample. */ -static void opd_handle_module_sample(unsigned long eip, u32 counter) +static void opd_handle_module_sample(vma_t eip, u32 counter) { struct opd_module * module; @@ -381,7 +381,7 @@ * Handle a sample in kernel address space or in a module. The sample is * output to the relevant image file. */ -void opd_handle_kernel_sample(unsigned long eip, u32 counter) +void opd_handle_kernel_sample(vma_t eip, u32 counter) { if (eip < kernel_end) { opd_stats[OPD_KERNEL]++; @@ -400,7 +400,7 @@ * Returns %1 if eip is in the address space starting at * kernel_start, %0 otherwise. */ -int opd_eip_is_kernel(unsigned long eip) +int opd_eip_is_kernel(vma_t eip) { return (eip >= kernel_start); } Index: daemon/opd_kernel.h =================================================================== RCS file: /cvsroot/oprofile/oprofile/daemon/opd_kernel.h,v retrieving revision 1.3 diff -u -r1.3 opd_kernel.h --- daemon/opd_kernel.h 3 Dec 2002 03:44:50 -0000 1.3 +++ daemon/opd_kernel.h 9 Jan 2003 02:07:15 -0000 @@ -17,7 +17,7 @@ void opd_init_kernel_image(void); void opd_parse_kernel_range(char const * arg); void opd_clear_module_info(void); -void opd_handle_kernel_sample(unsigned long eip, u32 counter); -int opd_eip_is_kernel(unsigned long eip); +void opd_handle_kernel_sample(vma_t eip, u32 counter); +int opd_eip_is_kernel(vma_t eip); #endif /* OPD_KERNEL_H */ Index: daemon/oprofiled.c =================================================================== RCS file: /cvsroot/oprofile/oprofile/daemon/oprofiled.c,v retrieving revision 1.19 diff -u -r1.19 oprofiled.c --- daemon/oprofiled.c 3 Jan 2003 15:54:04 -0000 1.19 +++ daemon/oprofiled.c 9 Jan 2003 02:07:25 -0000 @@ -58,6 +58,7 @@ int separate_samples; char * vmlinux; unsigned long opd_stats[OPD_MAX_STATS] = { 0, }; +size_t kernel_pointer_size; static char * kernel_range; static int showvers; @@ -447,9 +448,9 @@ * If the sample could be processed correctly, it is written * to the relevant sample file. */ -static void opd_do_samples(unsigned long * opd_buf, ssize_t count) +static void opd_do_samples(char const * opd_buf, ssize_t count) { - size_t num = count / sizeof(unsigned long); + size_t num = count / kernel_pointer_size; /* prevent signals from messing us up */ sigprocmask(SIG_BLOCK, &maskset, NULL); @@ -472,7 +473,7 @@ * Read some of a buffer from the device and process * the contents. */ -static void opd_do_read(unsigned long * buf, size_t size) +static void opd_do_read(char * buf, size_t size) { while (1) { ssize_t count = -1; @@ -580,15 +581,53 @@ } +#define EI_CLASS 4 +#define ELFCLASS32 1 +#define ELFCLASS64 2 + +static size_t opd_pointer_size() +{ + size_t size; + char elf_header[16]; + FILE * fp; + + if (!op_file_readable("/proc/kcore")) { + fprintf(stderr, "oprofiled: /proc/kcore not readable."); + goto guess; + } + + fp = op_open_file("/proc/kcore", "r"); + op_read_file(fp, &elf_header, 16); + op_close_file(fp); + + switch (elf_header[EI_CLASS]) { + case ELFCLASS32: + return 4; + case ELFCLASS64: + return 8; + } + + fprintf(stderr, "oprofiled: /proc/kcore has bad class.\n"); + +guess: + size = sizeof(unsigned long); + fprintf(stderr, "oprofiled: assuming pointer size is %u\n", + (unsigned int)size); + return size; +} + + int main(int argc, char const * argv[]) { - unsigned long * sbuf; + char * sbuf; size_t s_buf_bytesize; int i; opd_options(argc, argv); - s_buf_bytesize = opd_buf_size * sizeof(unsigned long); + kernel_pointer_size = opd_pointer_size(); + + s_buf_bytesize = opd_buf_size * kernel_pointer_size; sbuf = xmalloc(s_buf_bytesize); Index: libutil/op_types.h =================================================================== RCS file: /cvsroot/oprofile/oprofile/libutil/op_types.h,v retrieving revision 1.5 diff -u -r1.5 op_types.h --- libutil/op_types.h 7 Sep 2002 18:19:37 -0000 1.5 +++ libutil/op_types.h 9 Jan 2003 02:07:25 -0000 @@ -13,12 +13,22 @@ #define OP_TYPES_H #ifndef __KERNEL__ + +#include <sys/types.h> + /*@{\name miscellaneous types */ typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef int fd_t; /*@}*/ + +/** generic type for holding addresses */ +typedef u_int64_t vma_t; + +/** dcookie value */ +typedef u_int64_t cookie_t; + #else #include <linux/types.h> #endif |