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 |
From: Philippe E. <ph...@wa...> - 2003-01-09 07:55:15
|
John Levon wrote: > 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 ? a tiny > =================================================================== > 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 > +#define EI_CLASS 4 > +#define ELFCLASS32 1 > +#define ELFCLASS64 2 > + > +static size_t opd_pointer_size() void regards, Phil |
From: Randolph C. <ran...@ta...> - 2003-01-10 08:12:33
|
> 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 :) Well, it's certainly a step in the right direction... now oprofiled starts on my parisc64-linux box running 2.5.54... but it's not very stable and crashes quite readily. i haven't had time to look into this more today, but i'll look more this weekend. thanks! randolph -- Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/ |
From: Anton B. <an...@sa...> - 2003-01-27 07:39:53
|
Hi John > 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) I just got around to trying oprofile cvs and indeed it does work with ppc32 userspace and ppc64 kernel. Nice work. Does op_to_source work on x86? It isnt working for me and I went through and started changing some of the u32's to vma_t's but still no luck. Anton |
From: Philippe E. <ph...@wa...> - 2003-01-27 12:06:18
|
Anton Blanchard wrote: > Hi John >>The post-profile userspace should hopefully be OK now (maybe some little >>bits left) > > > I just got around to trying oprofile cvs and indeed it does work with > ppc32 userspace and ppc64 kernel. Nice work. > > Does op_to_source work on x86? It isnt working for me and I went through |^^^^^^^^^^^^^^^| it works on x86, what means ? --+ > and started changing some of the u32's to vma_t's but still no luck. > Falk Hueffner report it works on alpha (at least results seems sensible) regards, Phil |
From: Anton B. <an...@sa...> - 2003-01-27 12:24:57
|
> >I just got around to trying oprofile cvs and indeed it does work with > >ppc32 userspace and ppc64 kernel. Nice work. > > > >Does op_to_source work on x86? It isnt working for me and I went through > |^^^^^^^^^^^^^^^| > it works on x86, what means ? --+ Running a ppc32 oprofile executable on a ppc64 kernel. (ie 32bit executable, 64bit kernel). When I run with -V op_to_source shows all the function offsets have the top 32 bits truncated. > Falk Hueffner report it works on alpha (at least results seems sensible) I had a word with Alan Modra and there could be interesting things going on with bfd. Apparently on 32bit hosts, bfd_vma can be either a long or long long depending on how its compiled (eg compiling ppc32 binutils with ppc64 support will make bfd_vma a long long). Alpha is 64bit only so it wouldnt have this problem. sparc64, parisc64 and ppc64 do. Anton |
From: Philippe E. <ph...@wa...> - 2003-01-28 12:18:57
Attachments:
op_to_source.diff
|
Anton Blanchard wrote: > Running a ppc32 oprofile executable on a ppc64 kernel. (ie 32bit > executable, 64bit kernel). When I run with -V op_to_source shows all the > function offsets have the top 32 bits truncated. > > >>Falk Hueffner report it works on alpha (at least results seems sensible) > > > I had a word with Alan Modra and there could be interesting things going > on with bfd. Apparently on 32bit hosts, bfd_vma can be either a long or > long long depending on how its compiled (eg compiling ppc32 binutils with > ppc64 support will make bfd_vma a long long). > > Alpha is 64bit only so it wouldnt have this problem. sparc64, parisc64 and > ppc64 do. try the attached patch. It's probably not sufficient but it's required. If it don't work I need more feedback where vma are truncated, send me typical -V output for a truncated address regards, Phil |
From: Anton B. <an...@sa...> - 2003-01-29 15:02:16
|
> try the attached patch. It's probably not sufficient but it's > required. If it don't work I need more feedback where vma are > truncated, send me typical -V output for a truncated address Nice work, it fixes the problem. Apart from a few trivial bits I'll forward on (eg passing a long long in a syscall is arch/ABI dependent) oprofile is working perfectly with ppc32 userspace and ppc64 kernel. Anton |
From: Randolph C. <ran...@ta...> - 2003-01-29 16:04:42
|
> Nice work, it fixes the problem. Apart from a few trivial bits I'll > forward on (eg passing a long long in a syscall is arch/ABI dependent) > oprofile is working perfectly with ppc32 userspace and ppc64 kernel. parisc64 also needs this... so here's a patch :) Index: opd_cookie.h =================================================================== RCS file: /cvsroot/oprofile/oprofile/daemon/opd_cookie.h,v retrieving revision 1.2 diff -u -p -r1.2 daemon/opd_cookie.h --- daemon/opd_cookie.h 18 Jan 2003 16:12:35 -0000 1.2 +++ daemon/opd_cookie.h 29 Jan 2003 16:01:52 -0000 @@ -15,17 +15,38 @@ #include <unistd.h> #include "op_types.h" -#ifdef __i386__ +#if defined(__i386__) #define opd_nr_lookup_dcookie 253 +#elif defined(__hppa__) +#define opd_nr_lookup_dcookie 223 #elif defined(__alpha__) #define opd_nr_lookup_dcookie 406 #else #error Please define lookup_dcookie for your architecture #endif +#if defined(__hppa__) +static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) +{ + /* ABI specifies that 64-bit values cannot be passed on odd-numbered + * registers + */ + extern size_t kernel_pointer_size; + + if (kernel_pointer_size == 64) { + return syscall(opd_nr_lookup_dcookie, + (unsigned long)(cookie >> 32), + (unsigned long)(cookie & 0xffffffff), buf, size); + } else { + return syscall(opd_nr_lookup_dcookie, (unsigned long)cookie, + buf, size); + } +} +#else static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) { return syscall(opd_nr_lookup_dcookie, cookie, buf, size); } +#endif #endif /* OPD_COOKIE_H */ -- Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/ |
From: Randolph C. <ran...@ta...> - 2003-01-29 16:27:35
|
> + if (kernel_pointer_size == 64) { oops! as John pointed out to me, this should be 8 ... here's an updated patch randolph Index: opd_cookie.h =================================================================== RCS file: /cvsroot/oprofile/oprofile/daemon/opd_cookie.h,v retrieving revision 1.2 diff -u -p -r1.2 opd_cookie.h --- opd_cookie.h 18 Jan 2003 16:12:35 -0000 1.2 +++ opd_cookie.h 29 Jan 2003 16:01:52 -0000 @@ -15,17 +15,38 @@ #include <unistd.h> #include "op_types.h" -#ifdef __i386__ +#if defined(__i386__) #define opd_nr_lookup_dcookie 253 +#elif defined(__hppa__) +#define opd_nr_lookup_dcookie 223 #elif defined(__alpha__) #define opd_nr_lookup_dcookie 406 #else #error Please define lookup_dcookie for your architecture #endif +#if defined(__hppa__) +static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) +{ + /* ABI specifies that 64-bit values cannot be passed on odd-numbered + * registers + */ + extern size_t kernel_pointer_size; + + if (kernel_pointer_size == 8) { + return syscall(opd_nr_lookup_dcookie, + (unsigned long)(cookie >> 32), + (unsigned long)(cookie & 0xffffffff), buf, size); + } else { + return syscall(opd_nr_lookup_dcookie, (unsigned long)cookie, + buf, size); + } +} +#else static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) { return syscall(opd_nr_lookup_dcookie, cookie, buf, size); } +#endif #endif /* OPD_COOKIE_H */ |
From: Philippe E. <ph...@wa...> - 2003-01-30 14:33:10
|
Randolph Chung wrote: > Index: opd_cookie.h > +#if defined(__hppa__) > +static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) > +{ > + /* ABI specifies that 64-bit values cannot be passed on odd-numbered > + * registers > + */ > + extern size_t kernel_pointer_size; > + > + if (kernel_pointer_size == 8) { > + return syscall(opd_nr_lookup_dcookie, > + (unsigned long)(cookie >> 32), > + (unsigned long)(cookie & 0xffffffff), buf, size); > + } else { > + return syscall(opd_nr_lookup_dcookie, (unsigned long)cookie, > + buf, size); John, we discuss Randolph and me about this else part, it can't work and it seems there is no easy work-around. I'm committing something like: } else { printf("parsic 32 bits kernel unsupported\n"); exit(EXIT_FAILURE); Randolph, is the solution to add a wrapper in sys_parisc.c, in the same way as parisc_pread64() ? regards, Phil |
From: Randolph C. <ta...@de...> - 2003-01-30 15:17:07
|
> John, we discuss Randolph and me about this else part, > it can't work and it seems there is no easy work-around. > I'm committing something like: > > } else { > printf("parsic 32 bits kernel unsupported\n"); > exit(EXIT_FAILURE); parisc, not parsic :) > Randolph, is the solution to add a wrapper in sys_parisc.c, in the same > way as parisc_pread64() ? well, that's actually what i did to make it work with the patch i posted last time, but i had truncated the cookie parameter to 32-bit. i guess that's not ideal.... we can make it work the same as pread64 as you suggested to get it to work with a u64 cookie parameter.. that's probably a better idea. since you guys are planning a release today, i'd suggest let's use the same code for parisc that Anton posted for ppc64. just add a defined(__hppa__). i'll work on the kernel bits to make that work. thanks, and sorry for the confusion. randolph -- Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/ |
From: Philippe E. <ph...@wa...> - 2003-01-29 19:52:19
|
Anton Blanchard wrote: >>try the attached patch. It's probably not sufficient but it's >>required. If it don't work I need more feedback where vma are >>truncated, send me typical -V output for a truncated address > > > Nice work, it fixes the problem. Apart from a few trivial bits I'll > forward on (eg passing a long long in a syscall is arch/ABI dependent) > oprofile is working perfectly with ppc32 userspace and ppc64 kernel. John planned to release by tomorrow. If you want this change in oprofile 0.5 send your patch quickly please else the 0.5 tarball will be broken for ppc. Previous message in this thread show how we handled it for parisc. regards, Phil |
From: Anton B. <an...@sa...> - 2003-01-30 03:18:17
|
> John planned to release by tomorrow. If you want this change > in oprofile 0.5 send your patch quickly please else the 0.5 > tarball will be broken for ppc. Previous message in this thread > show how we handled it for parisc. Here is my current patch: - Add lookup_dcookie syscall number for ppc32/ppc64 - Fix lookup_dcookie on ppc32. The ABI passes long longs as an odd even register pair. When we call syscall() the long long cookie ends up in registers r5 and r6 (with r4 being empty). The syscall() function simply shifts r4-r8 down by one, leaving cookie in r4 and r5. To fix this we pass it in as two longs. - Pad 32bit addresses to 64bit when printing. We arent going to want this on x86 but it makes the output on ppc64 nicer. - Your patch for op_to_source - Fix op_start and opcontrol to handle ppc64 kernels. The start address in System.map is different - Fix opcontrol to handle 64bit kernel offsets. Im not sure why opcontrol was using perl where op_start just parsed it with grep/cut. Anton diff -ru oprofile/daemon/opd_cookie.h oprofile_work2/daemon/opd_cookie.h --- oprofile/daemon/opd_cookie.h 2003-01-19 03:12:35.000000000 +1100 +++ oprofile_work2/daemon/opd_cookie.h 2003-01-28 10:41:32.000000000 +1100 @@ -19,13 +19,23 @@ #define opd_nr_lookup_dcookie 253 #elif defined(__alpha__) #define opd_nr_lookup_dcookie 406 +#elif defined(__powerpc__) +#define opd_nr_lookup_dcookie 235 #else #error Please define lookup_dcookie for your architecture #endif +#if defined(__powerpc__) && !defined(__powerpc64__) +static int lookup_dcookie(u_int64_t cookie, char * buf, size_t size) +{ + return syscall(opd_nr_lookup_dcookie, (unsigned long)(cookie >> 32), + (unsigned long)(cookie & 0xffffffff), buf, size); +} +#else static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size) { return syscall(opd_nr_lookup_dcookie, cookie, buf, size); } +#endif #endif /* OPD_COOKIE_H */ diff -ru oprofile/pp/format_output.cpp oprofile_work2/pp/format_output.cpp --- oprofile/pp/format_output.cpp 2002-12-15 03:39:29.000000000 +1100 +++ oprofile_work2/pp/format_output.cpp 2003-01-28 10:42:02.000000000 +1100 @@ -332,7 +332,7 @@ { ostringstream out; - out << hex << setw(8) << setfill('0') << f.sample.vma; + out << hex << setw(16) << setfill('0') << f.sample.vma; return out.str(); } diff -ru oprofile/pp/op_to_source.cpp oprofile_work2/pp/op_to_source.cpp --- oprofile/pp/op_to_source.cpp 2002-12-15 03:39:29.000000000 +1100 +++ oprofile_work2/pp/op_to_source.cpp 2003-01-28 23:52:01.000000000 +1100 @@ -819,8 +819,9 @@ // do not use the bfd equivalent: // - it does not skip space at begin // - we does not need cross architecture compile so the native - // strtoul must work (assuming unsigned long can contain a vma) - bfd_vma vma = strtoul(str_vma.c_str(), NULL, 16); + // strtoull must work, assuming unsigned long long can contain a vma + // and on 32/64 bits box bfd_vma is 64 bits + bfd_vma vma = strtoull(str_vma.c_str(), NULL, 16); return samples->find_symbol(vma); } @@ -844,8 +845,9 @@ // do not use the bfd equivalent: // - it does not skip space at begin // - we does not need cross architecture compile so the native - // strtoul must work (assuming unsigned long can contain a vma) - bfd_vma vma = strtoul(str.c_str(), NULL, 16); + // strtoull must work, assuming unsigned long long can contain a vma + // and on 32/64 bits box bfd_vma is 64 bits + bfd_vma vma = strtoull(str.c_str(), NULL, 16); sample_entry const * sample = samples->find_sample(vma); if (sample) { diff -ru oprofile/utils/op_start_25 oprofile_work2/utils/op_start_25 --- oprofile/utils/op_start_25 2002-12-03 14:53:44.000000000 +1100 +++ oprofile_work2/utils/op_start_25 2003-01-30 14:00:14.000000000 +1100 @@ -141,6 +141,10 @@ return; fi tmp1=`nm $VMLINUX | grep ' A _text'` + # match start of kernel on ppc64 + if test -z "$tmp1"; then + tmp1=`nm $VMLINUX | grep ' T _stext'` + fi tmp2=`nm $VMLINUX | grep ' A _end'` if test -z "$tmp1" -o -z "$tmp2"; then echo "Couldn't determine kernel start/end" >&2 diff -ru oprofile/utils/opcontrol oprofile_work2/utils/opcontrol --- oprofile/utils/opcontrol 2003-01-15 23:19:21.000000000 +1100 +++ oprofile_work2/utils/opcontrol 2003-01-30 14:01:36.000000000 +1100 @@ -326,9 +326,15 @@ if test ! -z "$KERNEL_RANGE"; then return; fi - range_info=`objdump -h $VMLINUX | grep ".text "` - tmp1=`perl -le '($a, $b, $c, $d) = @ARGV; printf "%x\n", (hex($d))' $range_info` - tmp2=`perl -le '($a, $b, $c, $d) = @ARGV; printf "%x\n", (hex($c) + hex($d))' $range_info` + + tmp1=`nm $VMLINUX | grep ' A _text'` + # match start of kernel on ppc64 + if test -z "$tmp1"; then + tmp1=`nm $VMLINUX | grep ' T _stext'` + fi + tmp2=`nm $VMLINUX | grep ' A _end'` + tmp1=`echo $tmp1 | cut -d" " -f 1` + tmp2=`echo $tmp2 | cut -d" " -f 1` if test -z "$tmp1" -o -z "$tmp2"; then echo "Couldn't determine kernel start/end" >&2 |
From: John L. <le...@mo...> - 2003-01-30 03:27:21
|
On Thu, Jan 30, 2003 at 02:14:32PM +1100, Anton Blanchard wrote: > - Add lookup_dcookie syscall number for ppc32/ppc64 OK > - Fix lookup_dcookie on ppc32. The ABI passes long longs as an odd even Looks like you can use Randolph's version here. > - Pad 32bit addresses to 64bit when printing. We arent going to want this > on x86 but it makes the output on ppc64 nicer. This can wait until a solution that works for all is done. > - Fix opcontrol to handle 64bit kernel offsets. Im not sure > why opcontrol was using perl where op_start just parsed it with > grep/cut. Looking at the objdump header's values should be more portable. Will made this change : > - tmp1=`perl -le '($a, $b, $c, $d) = @ARGV; printf "%x\n", (hex($d))' $range_info` > - tmp2=`perl -le '($a, $b, $c, $d) = @ARGV; printf "%x\n", (hex($c) + hex($d))' $range_info` I'd prefer to just fix this code. Will ? regards john |
From: William C. <wc...@nc...> - 2003-01-30 03:48:19
|
John Levon wrote: > On Thu, Jan 30, 2003 at 02:14:32PM +1100, Anton Blanchard wrote: > > >>- Add lookup_dcookie syscall number for ppc32/ppc64 > > > OK > > >>- Fix lookup_dcookie on ppc32. The ABI passes long longs as an odd even > > > Looks like you can use Randolph's version here. > > >>- Pad 32bit addresses to 64bit when printing. We arent going to want this >> on x86 but it makes the output on ppc64 nicer. > > > This can wait until a solution that works for all is done. > > >>- Fix opcontrol to handle 64bit kernel offsets. Im not sure >> why opcontrol was using perl where op_start just parsed it with >> grep/cut. > > > Looking at the objdump header's values should be more portable. Will > made this change : > > >>- tmp1=`perl -le '($a, $b, $c, $d) = @ARGV; printf "%x\n", (hex($d))' $range_info` >>- tmp2=`perl -le '($a, $b, $c, $d) = @ARGV; printf "%x\n", (hex($c) + hex($d))' $range_info` > > > I'd prefer to just fix this code. Will ? The old implementation assumed that all kernels mark the end of the text with _stext. There were some kernels that I looked at the didn't mark the end in that manner. I don't remember which ones specifically (I looked at sparc, ia64, or ppc32). Rather than trying to enumerate all the possible special symbol name variation on the different targets and try to predict future name variations, I just decided to extract the start of text and the length using objdump and then compute the end. How did this code fail on the ppc64? I will take a look at this Thursday morning. -Will > > regards > john > > > ------------------------------------------------------- > This SF.NET email is sponsored by: > SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! > http://www.vasoftware.com > _______________________________________________ > oprofile-list mailing list > opr...@li... > https://lists.sourceforge.net/lists/listinfo/oprofile-list > |
From: Philippe E. <ph...@wa...> - 2003-01-30 14:26:30
|
William Cohen wrote: > John Levon wrote: > >>> - Fix opcontrol to handle 64bit kernel offsets. Im not sure >>> why opcontrol was using perl where op_start just parsed it with >>> grep/cut. >> >> >> >> Looking at the objdump header's values should be more portable. Will >> made this change : >> >> >>> - tmp1=`perl -le '($a, $b, $c, $d) = @ARGV; printf "%x\n", >>> (hex($d))' $range_info` >>> - tmp2=`perl -le '($a, $b, $c, $d) = @ARGV; printf "%x\n", >>> (hex($c) + hex($d))' $range_info` >> >> >> >> I'd prefer to just fix this code. Will ? > > > The old implementation assumed that all kernels mark the end of the text > with _stext. There were some kernels that I looked at the didn't mark > the end in that manner. I don't remember which ones specifically (I > looked at sparc, ia64, or ppc32). Rather than trying to enumerate all > the possible special symbol name variation on the different targets and > try to predict future name variations, I just decided to extract the > start of text and the length using objdump and then compute the end. > > How did this code fail on the ppc64? we can't do arithmetic in perl nor using print %[integer format] as we manipulate unsigned long long and perl can't handle them. String must be manipulate as it and passed to daemon. This means interface to daemon must be changed, passing start and size rather start and end. Anton is objdump -h parsing will give the same results as nm ? regards, Phil |
From: William C. <wc...@nc...> - 2003-01-30 14:52:30
|
Philippe Elie wrote: > William Cohen wrote: > > >> John Levon wrote: >> >>>> - Fix opcontrol to handle 64bit kernel offsets. Im not sure >>>> why opcontrol was using perl where op_start just parsed it with >>>> grep/cut. >>> >>> >>> >>> >>> Looking at the objdump header's values should be more portable. Will >>> made this change : >>> >>> >>>> - tmp1=`perl -le '($a, $b, $c, $d) = @ARGV; printf "%x\n", >>>> (hex($d))' $range_info` >>>> - tmp2=`perl -le '($a, $b, $c, $d) = @ARGV; printf "%x\n", >>>> (hex($c) + hex($d))' $range_info` >>> >>> >>> >>> >>> I'd prefer to just fix this code. Will ? >> >> >> >> The old implementation assumed that all kernels mark the end of the >> text with _stext. There were some kernels that I looked at the didn't >> mark the end in that manner. I don't remember which ones specifically >> (I looked at sparc, ia64, or ppc32). Rather than trying to enumerate >> all the possible special symbol name variation on the different >> targets and try to predict future name variations, I just decided to >> extract the start of text and the length using objdump and then >> compute the end. >> >> How did this code fail on the ppc64? > > > we can't do arithmetic in perl nor using print %[integer format] > as we manipulate unsigned long long and perl can't handle them. > String must be manipulate as it and passed to daemon. This means > interface to daemon must be changed, passing start and size rather > start and end. Using nm is not going to work with stripped kernel. Red Hat distributes some kernel as stripped, so going back to nm is not going to work either. Could we use the --adjust-vma option in objdump to compute the end address? first objdump used to get start address and length, make a second call to objdump with '--adjust-vma=length' and extract the end address from that. Having the deamon accept the start and length as an option sounds like less of a hack. -Will > > Anton is objdump -h parsing will give the same results as nm ? > > regards, > Phil > > > > ------------------------------------------------------- > This SF.NET email is sponsored by: > SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! > http://www.vasoftware.com > _______________________________________________ > oprofile-list mailing list > opr...@li... > https://lists.sourceforge.net/lists/listinfo/oprofile-list > |
From: Philippe E. <ph...@wa...> - 2003-01-30 14:43:00
|
John Levon wrote: > On Thu, Jan 30, 2003 at 02:14:32PM +1100, Anton Blanchard wrote: > > >>- Add lookup_dcookie syscall number for ppc32/ppc64 > > > OK > > >>- Fix lookup_dcookie on ppc32. The ABI passes long longs as an odd even > > > Looks like you can use Randolph's version here. No, it's broken, I'm commiting the opd_cookie.h part as it. Later if we get a working parisc identical to this one we will merge lookup_dcookie() definition. >>- Pad 32bit addresses to 64bit when printing. We arent going to want this >> on x86 but it makes the output on ppc64 nicer. > > > This can wait until a solution that works for all is done. The following is ok, it pessimes output on 32/64 when profiling a 32 bits application but will be sufficient for now // FIXME: do we need a better way to shrink output ? out << hex << setw(sizeof(bfd_vma) == 8 ? 16 : 8)) << setfill('0') << f.sample.vma; it remains to fix the kernel range parsing. regards, Phil |