Account Options

  1. Sign in
The old Google Groups will be going away soon.
Switch to the new Google Groups.
Google Groups Home
« Groups Home
[bionic] Support profiling for bionic
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  2 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Kito Cheng  
View profile  
 More options Dec 1 2011, 3:58 pm
From: Kito Cheng <k...@0xlab.org>
Date: Fri, 2 Dec 2011 04:58:37 +0800
Local: Thurs, Dec 1 2011 3:58 pm
Subject: [PATCH 1/2][bionic] Support profiling for bionic
 * Only support arm on current implementation.
 * Default profile file place in /data/loca/tmp/$(PROG).gmon.out
   - Output file path can change by environment variable PROFDIR.
 * Enable profiling by new option LOCAL_PROFILE_MODULE

Change-Id: Ib6326b7c1d63b941eaf1a1b86a2bf4432b70d677
---
 libc/arch-arm/include/machine/profile.h |  100 ++++++++++
 libc/include/sys/gmon.h                 |  175 +++++++++++++++++
 libc/kernel/arch-arm/asm/ucontext.h     |  102 ++++++++++
 libc/kernel/arch-x86/asm/ucontext.h     |   12 ++
 libgmon/Android.mk                      |   22 ++
 libgmon/gmon.c                          |  325 +++++++++++++++++++++++++++++++
 libgmon/mcount.c                        |  175 +++++++++++++++++
 7 files changed, 911 insertions(+), 0 deletions(-)
 create mode 100644 libc/arch-arm/include/machine/profile.h
 create mode 100644 libc/include/sys/gmon.h
 create mode 100644 libc/kernel/arch-arm/asm/ucontext.h
 create mode 100644 libc/kernel/arch-x86/asm/ucontext.h
 create mode 100644 libgmon/Android.mk
 create mode 100644 libgmon/gmon.c
 create mode 100644 libgmon/mcount.c

diff --git a/libc/arch-arm/include/machine/profile.h b/libc/arch-arm/include/machine/profile.h
new file mode 100644
index 0000000..6278216
--- /dev/null
+++ b/libc/arch-arm/include/machine/profile.h
@@ -0,0 +1,100 @@
+/*     $OpenBSD: profile.h,v 1.2 2011/09/20 22:02:13 miod Exp $        */
+/*     $NetBSD: profile.h,v 1.5 2002/03/24 15:49:40 bjh21 Exp $        */
+
+/*
+ * Copyright (c) 2001 Ben Harris
+ * Copyright (c) 1995-1996 Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mark Brinicombe.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ARM_PROFILE_H_
+#define _ARM_PROFILE_H_
+
+#define        _MCOUNT_DECL void _mcount
+
+/*
+ * Cannot implement mcount in C as GCC will trash the ip register when it
+ * pushes a trapframe. Pity we cannot insert assembly before the function
+ * prologue.
+ */
+
+#ifdef __ELF__
+#define MCOUNT_ASM_NAME "__gnu_mcount_nc"
+#ifdef PIC
+#define        PLTSYM          "(PLT)"
+#endif
+#else
+#define MCOUNT_ASM_NAME "mcount"
+#endif
+
+#ifndef PLTSYM
+#define        PLTSYM
+#endif
+
+#define        MCOUNT                                                          \
+       __asm__(".text");                                             \
+       __asm__(".align    0");                                               \
+       __asm__(".type     " MCOUNT_ASM_NAME ",%function");         \
+       __asm__(".global   " MCOUNT_ASM_NAME);                        \
+       __asm__(MCOUNT_ASM_NAME ":");                                 \
+       /*                                                              \
+        * Preserve registers that are trashed during mcount            \
+        */                                                             \
+       __asm__("stmfd     sp!, {r0-r3, lr}");                                \
+       /*                                                              \
+        * find the return address for mcount,                          \
+        * and the return address for mcount's caller.                  \
+        *                                                              \
+        * frompcindex = pc pushed by call into self.                   \
+        */                                                             \
+       __asm__("ldr       r0, [sp, #20]");                                   \
+       /*                                                              \
+        * selfpc = pc pushed by mcount call                            \
+        */                                                             \
+       __asm__("mov       r1, lr");                                  \
+       /*                                                              \
+        * Call the real mcount code                                    \
+        */                                                             \
+       __asm__("bl        " __STRING(_mcount) PLTSYM);               \
+       /*                                                              \
+        * Restore registers that were trashed during mcount            \
+        */                                                             \
+       __asm__("ldmfd     sp!, {r0-r3, pc}");
+
+#ifdef _KERNEL
+#include <arm/cpufunc.h>
+/*
+ * splhigh() and splx() are heavyweight, and call mcount().  Therefore
+ * we disabled interrupts (IRQ, but not FIQ) directly on the CPU.
+ *
+ * We're lucky that the CPSR and 's' both happen to be 'int's.
+ */
+#define        MCOUNT_ENTER    s = __set_cpsr_c(0x0080, 0x0080);       /* kill IRQ */
+#define        MCOUNT_EXIT     __set_cpsr_c(0xffffffff, s);    /* restore old value */
+#endif /* _KERNEL */
+
+#endif /* _ARM_PROFILE_H_ */
diff --git a/libc/include/sys/gmon.h b/libc/include/sys/gmon.h
new file mode 100644
index 0000000..3db3e1b
--- /dev/null
+++ b/libc/include/sys/gmon.h
@@ -0,0 +1,175 @@
+/*     $OpenBSD: gmon.h,v 1.4 2003/06/02 23:28:21 millert Exp $        */
+/*     $NetBSD: gmon.h,v 1.5 1996/04/09 20:55:30 cgd Exp $     */
+
+/*-
+ * Copyright (c) 1982, 1986, 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)gmon.h      8.2 (Berkeley) 1/4/94
+ */
+
+#ifndef _SYS_GMON_H_
+#define _SYS_GMON_H_
+
+#include <machine/profile.h>
+#include <sys/types.h>
+/*
+ * Structure prepended to gmon.out profiling data file.
+ */
+struct gmonhdr {
+       u_long  lpc;            /* base pc address of sample buffer */
+       u_long  hpc;            /* max pc address of sampled buffer */
+       int     ncnt;           /* size of sample buffer (plus this header) */
+       int     version;        /* version number */
+       int     profrate;       /* profiling clock rate */
+       int     spare[3];       /* reserved */
+};
+#define GMONVERSION    0x00051879
+
+/*
+ * histogram counters are unsigned shorts (according to the kernel).
+ */
+#define        HISTCOUNTER     unsigned short
+
+/*
+ * fraction of text space to allocate for histogram counters here, 1/2
+ */
+#define        HISTFRACTION    2
+
+/*
+ * Fraction of text space to allocate for from hash buckets.
+ * The value of HASHFRACTION is based on the minimum number of bytes
+ * of separation between two subroutine call points in the object code.
+ * Given MIN_SUBR_SEPARATION bytes of separation the value of
+ * HASHFRACTION is calculated as:
+ *
+ *     HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1);
+ *
+ * For example, on the VAX, the shortest two call sequence is:
+ *
+ *     calls   $0,(r0)
+ *     calls   $0,(r0)
+ *
+ * which is separated by only three bytes, thus HASHFRACTION is
+ * calculated as:
+ *
+ *     HASHFRACTION = 3 / (2 * 2 - 1) = 1
+ *
+ * Note that the division above rounds down, thus if MIN_SUBR_FRACTION
+ * is less than three, this algorithm will not work!
+ *
+ * In practice, however, call instructions are rarely at a minimal
+ * distance.  Hence, we will define HASHFRACTION to be 2 across all
+ * architectures.  This saves a reasonable amount of space for
+ * profiling data structures without (in practice) sacrificing
+ * any granularity.
+ */
+#define        HASHFRACTION    2
+
+/*
+ * percent of text space to allocate for tostructs with a minimum.
+ */
+#define ARCDENSITY     2
+#define MINARCS                50
+#define MAXARCS                ((1 << (8 * sizeof(HISTCOUNTER))) - 2)
+
+struct tostruct {
+       u_long  selfpc;
+       long    count;
+       u_short link;
+       u_short pad;
+};
+
+/*
+ * a raw arc, with pointers to the calling site and
+ * the called site and a count.
+ */
+struct rawarc {
+       u_long  raw_frompc;
+       u_long  raw_selfpc;
+       long    raw_count;
+};
+
+/*
+ * general rounding functions.
+ */
+#define ROUNDDOWN(x,y) (((x)/(y))*(y))
+#define ROUNDUP(x,y)   ((((x)+(y)-1)/(y))*(y))
+
+/*
+ * The profiling data structures are housed in this structure.
+ */
+struct gmonparam {
+       int             state;
+       u_short         *kcount;
+       u_long          kcountsize;
+       u_short         *froms;
+       u_long          fromssize;
+       struct tostruct *tos;
+       u_long          tossize;
+       long            tolimit;
+       u_long          lowpc;
+       u_long          highpc;
+       u_long          textsize;
+       u_long          hashfraction;
+};
+extern struct gmonparam _gmonparam;
+
+/*
+ * Possible states of profiling.
+ */
+#define        GMON_PROF_ON    0
+#define        GMON_PROF_BUSY  1
+#define        GMON_PROF_ERROR 2
+#define        GMON_PROF_OFF   3
+
+/*
+ * Sysctl definitions for extracting profiling information from the kernel.
+ */
+#define        GPROF_STATE     0       /* int: profiling enabling variable */
...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Discussion subject changed to "[bionic] aprof : android profiler" by Kito Cheng
Kito Cheng  
View profile  
 More options Dec 1 2011, 3:58 pm
From: Kito Cheng <k...@0xlab.org>
Date: Fri, 2 Dec 2011 04:58:38 +0800
Local: Thurs, Dec 1 2011 3:58 pm
Subject: [PATCH 2/2][bionic] aprof : android profiler
  * Support profiling shared libraries (include opened by dlopen)!
  * Profile file is output to /data/loca/tmp/agmon.out
  * Enable profiling by new option LOCAL_ENABLE_APROF
  * Only support arm on current implementation
  * Profiling file format is *incompatible* with gprof

Change-Id: Iafe425ed32dbb04652cfd66f9c40c470a75207bf
---
 libaprof/Android.mk              |   98 ++++++++++++++
 libaprof/libaprof-aux.c          |   20 +++
 libaprof/libaprof-static.c       |  264 ++++++++++++++++++++++++++++++++++++++
 libaprof/libaprof-stubs.c        |    7 +
 libaprof/libaprof.c              |   24 ++++
 libaprof/libaprof.h              |   73 +++++++++++
 libaprof/test/Android.mk         |   72 ++++++++++
 libaprof/test/libprof-test.c     |    7 +
 libaprof/test/profiler-test-dl.c |   24 ++++
 libaprof/test/profiler-test.c    |   20 +++
 linker/Android.mk                |   13 ++-
 linker/linker.c                  |   16 ++-
 linker/linker.h                  |   20 +++
 13 files changed, 653 insertions(+), 5 deletions(-)
 create mode 100644 libaprof/Android.mk
 create mode 100644 libaprof/libaprof-aux.c
 create mode 100644 libaprof/libaprof-static.c
 create mode 100644 libaprof/libaprof-stubs.c
 create mode 100644 libaprof/libaprof.c
 create mode 100644 libaprof/libaprof.h
 create mode 100644 libaprof/test/Android.mk
 create mode 100644 libaprof/test/libprof-test.c
 create mode 100644 libaprof/test/profiler-test-dl.c
 create mode 100644 libaprof/test/profiler-test.c

diff --git a/libaprof/Android.mk b/libaprof/Android.mk
new file mode 100644
index 0000000..84f0fab
--- /dev/null
+++ b/libaprof/Android.mk
@@ -0,0 +1,98 @@
+#
+# libaprof implement the mcount function to enable generate profile
+# by `-pg` option.
+#
+
+ifeq ($(TARGET_ARCH),arm)
+
+LOCAL_PATH:= $(call my-dir)
+
+#
+# There are stubs for functions only, they are actually defined
+# in the dynamic linker (aprof.c), and hijacked at runtime.
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_SRC_FILES := libaprof-stubs.c
+
+LOCAL_MODULE := libaprof-stubs
+
+include $(BUILD_SHARED_LIBRARY)
+
+#
+# libgmon with aprof extension
+#
+# The aprof can provide call graph and sample based profiling data
+# for shared libraries, static libraries and executable.
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_SRC_FILES := libaprof.c
+
+LOCAL_MODULE:= libaprof
+
+LOCAL_SHARED_LIBRARIES := libaprof-stubs
+
+include $(BUILD_SHARED_LIBRARY)
+
+#
+# libaprof for mcount
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_SRC_FILES := libaprof.c
+
+LOCAL_MODULE:= libaprof
+
+include $(BUILD_STATIC_LIBRARY)
+
+
+#
+# libaprof for static link executable
+#
+# Implment the simplified version for aprof_init, aprof_fini and aprof_mcount.
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_SRC_FILES := libaprof-static.c
+
+LOCAL_MODULE:= libaprof-static
+
+include $(BUILD_STATIC_LIBRARY)
+
+#
+# libaprof-aux libraries for register constructor and destructor for aprof
+#
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_SRC_FILES := libaprof-aux.c
+
+LOCAL_MODULE:= libaprof-aux
+
+include $(BUILD_STATIC_LIBRARY)
+
+endif
diff --git a/libaprof/libaprof-aux.c b/libaprof/libaprof-aux.c
new file mode 100644
index 0000000..1f7cdc1
--- /dev/null
+++ b/libaprof/libaprof-aux.c
@@ -0,0 +1,20 @@
+/*
+ * libgmon aux library for register
+ * constructor and destructor for aprof
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/gmon.h>
+
+extern void aprof_init();
+extern void aprof_fini();
+
+void __libgmon_aprof_ctor() __attribute__((constructor));
+
+void __libgmon_aprof_ctor()
+{
+    printf("__libgmon_aprof_ctor\n");
+    aprof_init();
+    atexit(&aprof_fini);
+}
diff --git a/libaprof/libaprof-static.c b/libaprof/libaprof-static.c
new file mode 100644
index 0000000..a9a88ad
--- /dev/null
+++ b/libaprof/libaprof-static.c
@@ -0,0 +1,264 @@
+/*
+ * libaprof-static are imp
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/gmon.h>
+#include <sys/mman.h>
+#include <asm/sigcontext.h>
+#include <asm/ucontext.h>
+
+#include <libaprof.h>
+
+extern char etext[];
+extern char *__progname;
+
+static uintptr_t textsize;
+
+static uint32_t bin_size;
+static uint16_t *bins;
+
+static size_t fromssize;
+static uint16_t *froms;
+
+static struct tostruct *tos;
+static size_t tolimit;
+static size_t tossize;
+
+void aprof_init();
+void aprof_fini();
+
+static void aprof_sampler (int sig __attribute__((unused)),
+                           siginfo_t *sii __attribute__((unused)),
+                           void *context)
+{
+    struct ucontext *uc = (struct ucontext*)context;
+    uintptr_t pc = uc->uc_mcontext.arm_pc;
+    size_t i = (pc / 2) / HASHFRACTION;
+    bins[i]++;
+}
+
+void aprof_init() {
+    struct sigaction sigact;
+    struct itimerval timer;
+    void *addr;
+    size_t tossize;
+    /*
+     *  Allocate memory
+     */
+    textsize = (uintptr_t)(&etext[0]);
+    bin_size =  textsize / HISTFRACTION;
+    tolimit = textsize * ARCDENSITY / 100;
+    if (tolimit < MINARCS)
+        tolimit = MINARCS;
+    else if (tolimit > MAXARCS)
+        tolimit = MAXARCS;
+    tossize = tolimit * sizeof(struct tostruct);
+
+    addr = mmap((void *)0, bin_size,  PROT_READ|PROT_WRITE,
+                MAP_ANON|MAP_PRIVATE, -1, (off_t)0);
+    if (addr == MAP_FAILED)
+        goto mapfailed;
+    bins = addr;
+
+    fromssize = textsize / HASHFRACTION;
+    addr = mmap((void *)0, fromssize,  PROT_READ|PROT_WRITE,
+        MAP_ANON|MAP_PRIVATE, -1, (off_t)0);
+    if (addr == MAP_FAILED)
+        goto mapfailed;
+    froms = addr;
+
+    addr = mmap((void *)0, tossize,  PROT_READ|PROT_WRITE,
+                MAP_ANON|MAP_PRIVATE, -1, (off_t)0);
+    if (addr == MAP_FAILED)
+        goto mapfailed;
+    tos = addr;
+    tos[0].link = 0;
+
+    /*
+     * Setup timer and hander for sample
+     */
+    sigact.sa_sigaction =  &aprof_sampler;
+    sigact.sa_flags = SA_RESTART | SA_SIGINFO;
+    sigfillset(&sigact.sa_mask);
+
+    if (sigaction(SIGPROF, &sigact, NULL) < 0) {
+        /* Error */
+        return;
+    }
+
+    timer.it_value.tv_sec = 0;
+    timer.it_value.tv_usec = 1000000 / (PROFRATE*10);
+    timer.it_interval = timer.it_value;
+    if (setitimer(ITIMER_PROF, &timer, NULL) < 0) {
+        /* Error */
+        return;
+    }
+    return;
+
+mapfailed:
+    if (bins != NULL) {
+        munmap(bins, bin_size);
+        bins = NULL;
+    }  
+    if (froms != NULL) {
+        munmap(froms, fromssize);
+        froms = NULL;
+    }  
+    if (tos != NULL) {
+        munmap(tos, tossize);
+        tos = NULL;
+    }
+}
+
+void aprof_fini() {
+    int fd = open("/data/local/tmp/agmon.out", O_CREAT|O_TRUNC|O_WRONLY, 0664);
+    uint32_t len = strlen(__progname);
+    uint32_t header_type;
+    const char aprof_tag[] = APROF_TAG;
+    uint32_t version = APROF_VERSION;
+    uint32_t pointer_size = sizeof(intptr_t);
+    uint32_t sample_rate = PROFRATE;
+    uint32_t base = 0;
+
+    /* Trun off aprof_sampler */
+    sigaction(SIGPROF, NULL, NULL);
+    setitimer(ITIMER_PROF, NULL, NULL);
+
+    /* Write aprof profiling file header */
+    write(fd, aprof_tag, APROF_TAG_LENGTH);
+    write(fd, &version, sizeof(uint32_t));
+    write(fd, &sample_rate, sizeof(uint32_t));
+    write(fd, &pointer_size, sizeof(uint32_t));
+
+    /* Write histogram records */
+    header_type = APROF_EXECUTABLE_HISTOGRAM_HEADER;
+    write(fd, &header_type, sizeof(uint32_t));
+    write(fd, &len, sizeof(uint32_t));
+    write(fd, __progname, len);
+    write(fd, &base, sizeof(uintptr_t));
+    write(fd, &textsize, sizeof(uintptr_t));
+    write(fd, &bin_size, sizeof(uint32_t));
+    write(fd, bins, bin_size);
+    /* Write call graph records */
+    header_type = APROF_CALL_GRAPH_HEADER;
+    write(fd, &header_type, sizeof(uint32_t));
+    int fromindex, endfrom, toindex;
+    uintptr_t frompc;
+    uint32_t num_edges = 0;
+    /* Go through for count how many edges. */
+    endfrom = fromssize / sizeof(*froms);
+    for (fromindex = 0; fromindex < endfrom; fromindex++) {
+        if (froms[fromindex] == 0) continue;
+        for (toindex = froms[fromindex]; toindex != 0;
+             toindex = tos[toindex].link) {
+            num_edges++;
+        }
+    }
+
+    write(fd, &num_edges, sizeof(uint32_t));
+    endfrom = fromssize / sizeof(*froms);
+    for (fromindex = 0; fromindex < endfrom; fromindex++) {
+        if (froms[fromindex] == 0)
+            continue;
+
+        frompc = fromindex * HASHFRACTION * sizeof(*froms);
+        for (toindex = froms[fromindex]; toindex != 0;
+             toindex = tos[toindex].link) {
+            uintptr_t selfpc = tos[toindex].selfpc;
+            uint32_t count = tos[toindex].count;
+            write(fd, &frompc, sizeof(uintptr_t));
+            write(fd, &selfpc, sizeof(uintptr_t));
+            write(fd, &count, sizeof(uint32_t));
+        }
+    }
+}
+
+void aprof_mcount(uintptr_t frompc, uintptr_t selfpc) {
+    unsigned short *frompcindex;
+    struct tostruct *top, *prevtop;
+    unsigned long toindex;
+    uintptr_t frompc_offset;
+    frompc_offset = frompc;
+    frompcindex =
+        &froms[frompc_offset / (HASHFRACTION * sizeof(*froms))];
+    toindex = *frompcindex;
+    if (toindex == 0) {
+        /*  first time traversing this arc */
+        toindex = ++tos[0].link;
+        if (toindex >= tolimit)
+            /* halt further profiling */
+            goto overflow;
+
+        *frompcindex = toindex;
+        top = &tos[toindex];
+        top->selfpc = selfpc;
+        top->count = 1;
+        top->link = 0;
+        return;
+    }
+
+    top =
...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »