aboutsummaryrefslogtreecommitdiff
path: root/gprofng/src/Exp_Layout.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng/src/Exp_Layout.cc')
-rw-r--r--gprofng/src/Exp_Layout.cc422
1 files changed, 422 insertions, 0 deletions
diff --git a/gprofng/src/Exp_Layout.cc b/gprofng/src/Exp_Layout.cc
new file mode 100644
index 0000000..dfe1432
--- /dev/null
+++ b/gprofng/src/Exp_Layout.cc
@@ -0,0 +1,422 @@
+/* Copyright (C) 2021 Free Software Foundation, Inc.
+ Contributed by Oracle.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "config.h"
+#include "CallStack.h"
+#include "DbeSession.h"
+#include "Exp_Layout.h"
+#include "Experiment.h"
+#include "Function.h"
+#include "Table.h"
+#include "dbe_types.h"
+#include "util.h"
+
+/*
+ * PrUsage is a class which wraps access to the values of prusage
+ * system structure. It was expanded to 64 bit entities in 2.7
+ * (experiment version 6 & 7).
+ */
+PrUsage::PrUsage ()
+{
+ pr_tstamp = pr_create = pr_term = pr_rtime = (hrtime_t) 0;
+ pr_utime = pr_stime = pr_ttime = pr_tftime = pr_dftime = (hrtime_t) 0;
+ pr_kftime = pr_ltime = pr_slptime = pr_wtime = pr_stoptime = (hrtime_t) 0;
+
+ pr_minf = pr_majf = pr_nswap = pr_inblk = pr_oublk = 0;
+ pr_msnd = pr_mrcv = pr_sigs = pr_vctx = pr_ictx = pr_sysc = pr_ioch = 0;
+}
+
+/*
+ * Resource usage. /proc/<pid>/usage /proc/<pid>/lwp/<lwpid>/lwpusage
+ */
+struct timestruc_32
+{ /* v8 timestruc_t */
+ uint32_t tv_sec; /* seconds */
+ uint32_t tv_nsec; /* and nanoseconds */
+};
+
+typedef struct ana_prusage
+{
+ id_t pr_lwpid; /* lwp id. 0: process or defunct */
+ int pr_count; /* number of contributing lwps */
+ timestruc_32 pr_tstamp; /* current time stamp */
+ timestruc_32 pr_create; /* process/lwp creation time stamp */
+ timestruc_32 pr_term; /* process/lwp termination time stamp */
+ timestruc_32 pr_rtime; /* total lwp real (elapsed) time */
+ timestruc_32 pr_utime; /* user level cpu time */
+ timestruc_32 pr_stime; /* system call cpu time */
+ timestruc_32 pr_ttime; /* other system trap cpu time */
+ timestruc_32 pr_tftime; /* text page fault sleep time */
+ timestruc_32 pr_dftime; /* data page fault sleep time */
+ timestruc_32 pr_kftime; /* kernel page fault sleep time */
+ timestruc_32 pr_ltime; /* user lock wait sleep time */
+ timestruc_32 pr_slptime; /* all other sleep time */
+ timestruc_32 pr_wtime; /* wait-cpu (latency) time */
+ timestruc_32 pr_stoptime; /* stopped time */
+ timestruc_32 filltime[6]; /* filler for future expansion */
+ uint32_t pr_minf; /* minor page faults */
+ uint32_t pr_majf; /* major page faults */
+ uint32_t pr_nswap; /* swaps */
+ uint32_t pr_inblk; /* input blocks */
+ uint32_t pr_oublk; /* output blocks */
+ uint32_t pr_msnd; /* messages sent */
+ uint32_t pr_mrcv; /* messages received */
+ uint32_t pr_sigs; /* signals received */
+ uint32_t pr_vctx; /* voluntary context switches */
+ uint32_t pr_ictx; /* involuntary context switches */
+ uint32_t pr_sysc; /* system calls */
+ uint32_t pr_ioch; /* chars read and written */
+ uint32_t filler[10]; /* filler for future expansion */
+} raw_prusage_32;
+
+uint64_t
+PrUsage::bind32Size ()
+{
+ uint64_t bindSize = sizeof (raw_prusage_32);
+ return bindSize;
+}
+
+#define timestruc2hr(x) ((hrtime_t)(x).tv_sec*NANOSEC + (hrtime_t)(x).tv_nsec)
+
+PrUsage *
+PrUsage::bind32 (void *p, bool need_swap_endian)
+{
+ if (p == NULL)
+ return NULL;
+ raw_prusage_32 pu, *tmp = (raw_prusage_32*) p;
+ if (need_swap_endian)
+ {
+ pu = *tmp;
+ tmp = &pu;
+ SWAP_ENDIAN (pu.pr_tstamp.tv_sec);
+ SWAP_ENDIAN (pu.pr_tstamp.tv_nsec);
+ SWAP_ENDIAN (pu.pr_create.tv_sec);
+ SWAP_ENDIAN (pu.pr_create.tv_nsec);
+ SWAP_ENDIAN (pu.pr_term.tv_sec);
+ SWAP_ENDIAN (pu.pr_term.tv_nsec);
+ SWAP_ENDIAN (pu.pr_rtime.tv_sec);
+ SWAP_ENDIAN (pu.pr_rtime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_utime.tv_sec);
+ SWAP_ENDIAN (pu.pr_utime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_stime.tv_sec);
+ SWAP_ENDIAN (pu.pr_stime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_ttime.tv_sec);
+ SWAP_ENDIAN (pu.pr_ttime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_tftime.tv_sec);
+ SWAP_ENDIAN (pu.pr_tftime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_dftime.tv_sec);
+ SWAP_ENDIAN (pu.pr_dftime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_kftime.tv_sec);
+ SWAP_ENDIAN (pu.pr_kftime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_ltime.tv_sec);
+ SWAP_ENDIAN (pu.pr_ltime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_slptime.tv_sec);
+ SWAP_ENDIAN (pu.pr_slptime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_wtime.tv_sec);
+ SWAP_ENDIAN (pu.pr_wtime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_stoptime.tv_sec);
+ SWAP_ENDIAN (pu.pr_stoptime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_minf);
+ SWAP_ENDIAN (pu.pr_majf);
+ SWAP_ENDIAN (pu.pr_nswap);
+ SWAP_ENDIAN (pu.pr_inblk);
+ SWAP_ENDIAN (pu.pr_oublk);
+ SWAP_ENDIAN (pu.pr_msnd);
+ SWAP_ENDIAN (pu.pr_mrcv);
+ SWAP_ENDIAN (pu.pr_sigs);
+ SWAP_ENDIAN (pu.pr_vctx);
+ SWAP_ENDIAN (pu.pr_ictx);
+ SWAP_ENDIAN (pu.pr_sysc);
+ SWAP_ENDIAN (pu.pr_ioch);
+ }
+ pr_tstamp = timestruc2hr (tmp->pr_tstamp);
+ pr_create = timestruc2hr (tmp->pr_create);
+ pr_term = timestruc2hr (tmp->pr_term);
+ pr_rtime = timestruc2hr (tmp->pr_rtime);
+ pr_utime = timestruc2hr (tmp->pr_utime);
+ pr_stime = timestruc2hr (tmp->pr_stime);
+ pr_ttime = timestruc2hr (tmp->pr_ttime);
+ pr_tftime = timestruc2hr (tmp->pr_tftime);
+ pr_dftime = timestruc2hr (tmp->pr_dftime);
+ pr_kftime = timestruc2hr (tmp->pr_kftime);
+ pr_ltime = timestruc2hr (tmp->pr_ltime);
+ pr_slptime = timestruc2hr (tmp->pr_slptime);
+ pr_wtime = timestruc2hr (tmp->pr_wtime);
+ pr_stoptime = timestruc2hr (tmp->pr_stoptime);
+ pr_minf = tmp->pr_minf;
+ pr_majf = tmp->pr_majf;
+ pr_nswap = tmp->pr_nswap;
+ pr_inblk = tmp->pr_inblk;
+ pr_oublk = tmp->pr_oublk;
+ pr_msnd = tmp->pr_msnd;
+ pr_mrcv = tmp->pr_mrcv;
+ pr_sigs = tmp->pr_sigs;
+ pr_vctx = tmp->pr_vctx;
+ pr_ictx = tmp->pr_ictx;
+ pr_sysc = tmp->pr_sysc;
+ pr_ioch = tmp->pr_ioch;
+ return this;
+}
+
+struct timestruc_64
+{ /* 64-bit timestruc_t */
+ uint64_t tv_sec; /* seconds */
+ uint64_t tv_nsec; /* and nanoseconds */
+};
+
+typedef struct
+{
+ id_t pr_lwpid; /* lwp id. 0: process or defunct */
+ int pr_count; /* number of contributing lwps */
+ timestruc_64 pr_tstamp; /* current time stamp */
+ timestruc_64 pr_create; /* process/lwp creation time stamp */
+ timestruc_64 pr_term; /* process/lwp termination time stamp */
+ timestruc_64 pr_rtime; /* total lwp real (elapsed) time */
+ timestruc_64 pr_utime; /* user level cpu time */
+ timestruc_64 pr_stime; /* system call cpu time */
+ timestruc_64 pr_ttime; /* other system trap cpu time */
+ timestruc_64 pr_tftime; /* text page fault sleep time */
+ timestruc_64 pr_dftime; /* data page fault sleep time */
+ timestruc_64 pr_kftime; /* kernel page fault sleep time */
+ timestruc_64 pr_ltime; /* user lock wait sleep time */
+ timestruc_64 pr_slptime; /* all other sleep time */
+ timestruc_64 pr_wtime; /* wait-cpu (latency) time */
+ timestruc_64 pr_stoptime; /* stopped time */
+ timestruc_64 filltime[6]; /* filler for future expansion */
+ uint64_t pr_minf; /* minor page faults */
+ uint64_t pr_majf; /* major page faults */
+ uint64_t pr_nswap; /* swaps */
+ uint64_t pr_inblk; /* input blocks */
+ uint64_t pr_oublk; /* output blocks */
+ uint64_t pr_msnd; /* messages sent */
+ uint64_t pr_mrcv; /* messages received */
+ uint64_t pr_sigs; /* signals received */
+ uint64_t pr_vctx; /* voluntary context switches */
+ uint64_t pr_ictx; /* involuntary context switches */
+ uint64_t pr_sysc; /* system calls */
+ uint64_t pr_ioch; /* chars read and written */
+ uint64_t filler[10]; /* filler for future expansion */
+} raw_prusage_64;
+
+uint64_t
+PrUsage::bind64Size ()
+{
+ uint64_t bindSize = sizeof (raw_prusage_64);
+ return bindSize;
+}
+
+PrUsage *
+PrUsage::bind64 (void *p, bool need_swap_endian)
+{
+ if (p == NULL)
+ {
+ return NULL;
+ }
+ raw_prusage_64 pu, *tmp = (raw_prusage_64*) p;
+ if (need_swap_endian)
+ {
+ pu = *tmp;
+ tmp = &pu;
+ SWAP_ENDIAN (pu.pr_tstamp.tv_sec);
+ SWAP_ENDIAN (pu.pr_tstamp.tv_nsec);
+ SWAP_ENDIAN (pu.pr_create.tv_sec);
+ SWAP_ENDIAN (pu.pr_create.tv_nsec);
+ SWAP_ENDIAN (pu.pr_term.tv_sec);
+ SWAP_ENDIAN (pu.pr_term.tv_nsec);
+ SWAP_ENDIAN (pu.pr_rtime.tv_sec);
+ SWAP_ENDIAN (pu.pr_rtime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_utime.tv_sec);
+ SWAP_ENDIAN (pu.pr_utime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_stime.tv_sec);
+ SWAP_ENDIAN (pu.pr_stime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_ttime.tv_sec);
+ SWAP_ENDIAN (pu.pr_ttime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_tftime.tv_sec);
+ SWAP_ENDIAN (pu.pr_tftime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_dftime.tv_sec);
+ SWAP_ENDIAN (pu.pr_dftime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_kftime.tv_sec);
+ SWAP_ENDIAN (pu.pr_kftime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_ltime.tv_sec);
+ SWAP_ENDIAN (pu.pr_ltime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_slptime.tv_sec);
+ SWAP_ENDIAN (pu.pr_slptime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_wtime.tv_sec);
+ SWAP_ENDIAN (pu.pr_wtime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_stoptime.tv_sec);
+ SWAP_ENDIAN (pu.pr_stoptime.tv_nsec);
+ SWAP_ENDIAN (pu.pr_minf);
+ SWAP_ENDIAN (pu.pr_majf);
+ SWAP_ENDIAN (pu.pr_nswap);
+ SWAP_ENDIAN (pu.pr_inblk);
+ SWAP_ENDIAN (pu.pr_oublk);
+ SWAP_ENDIAN (pu.pr_msnd);
+ SWAP_ENDIAN (pu.pr_mrcv);
+ SWAP_ENDIAN (pu.pr_sigs);
+ SWAP_ENDIAN (pu.pr_vctx);
+ SWAP_ENDIAN (pu.pr_ictx);
+ SWAP_ENDIAN (pu.pr_sysc);
+ SWAP_ENDIAN (pu.pr_ioch);
+ }
+
+ pr_tstamp = timestruc2hr (tmp->pr_tstamp);
+ pr_create = timestruc2hr (tmp->pr_create);
+ pr_term = timestruc2hr (tmp->pr_term);
+ pr_rtime = timestruc2hr (tmp->pr_rtime);
+ pr_utime = timestruc2hr (tmp->pr_utime);
+ pr_stime = timestruc2hr (tmp->pr_stime);
+ pr_ttime = timestruc2hr (tmp->pr_ttime);
+ pr_tftime = timestruc2hr (tmp->pr_tftime);
+ pr_dftime = timestruc2hr (tmp->pr_dftime);
+ pr_kftime = timestruc2hr (tmp->pr_kftime);
+ pr_ltime = timestruc2hr (tmp->pr_ltime);
+ pr_slptime = timestruc2hr (tmp->pr_slptime);
+ pr_wtime = timestruc2hr (tmp->pr_wtime);
+ pr_stoptime = timestruc2hr (tmp->pr_stoptime);
+ pr_minf = tmp->pr_minf;
+ pr_majf = tmp->pr_majf;
+ pr_nswap = tmp->pr_nswap;
+ pr_inblk = tmp->pr_inblk;
+ pr_oublk = tmp->pr_oublk;
+ pr_msnd = tmp->pr_msnd;
+ pr_mrcv = tmp->pr_mrcv;
+ pr_sigs = tmp->pr_sigs;
+ pr_vctx = tmp->pr_vctx;
+ pr_ictx = tmp->pr_ictx;
+ pr_sysc = tmp->pr_sysc;
+ pr_ioch = tmp->pr_ioch;
+ return this;
+}
+
+Vector<long long> *
+PrUsage::getMstateValues ()
+{
+ const PrUsage *prusage = this;
+ Vector<long long> *states = new Vector<long long>;
+ states->store (0, prusage->pr_utime);
+ states->store (1, prusage->pr_stime);
+ states->store (2, prusage->pr_ttime);
+ states->store (3, prusage->pr_tftime);
+ states->store (4, prusage->pr_dftime);
+ states->store (5, prusage->pr_kftime);
+ states->store (6, prusage->pr_ltime);
+ states->store (7, prusage->pr_slptime);
+ states->store (8, prusage->pr_wtime);
+ states->store (9, prusage->pr_stoptime);
+ assert (LMS_NUM_SOLARIS_MSTATES == states->size ());
+ return states;
+}
+
+void* CommonPacket::jvm_overhead = NULL;
+
+CommonPacket::CommonPacket ()
+{
+ for (int i = 0; i < NTAGS; i++)
+ tags[i] = 0;
+ tstamp = 0;
+ jthread_TBR = NULL;
+ frinfo = 0;
+ leafpc = 0;
+ nat_stack = NULL;
+ user_stack = NULL;
+}
+
+int
+CommonPacket::cmp (const void *a, const void *b)
+{
+ if ((*(CommonPacket **) a)->tstamp > (*(CommonPacket **) b)->tstamp)
+ return 1;
+ else if ((*(CommonPacket **) a)->tstamp < (*(CommonPacket **) b)->tstamp)
+ return -1;
+ else
+ return 0;
+}
+
+void *
+CommonPacket::getStack (VMode view_mode)
+{
+ if (view_mode == VMODE_MACHINE)
+ return nat_stack;
+ else if (view_mode == VMODE_USER)
+ {
+ if (jthread_TBR == JTHREAD_NONE || (jthread_TBR && jthread_TBR->is_system ()))
+ return jvm_overhead;
+ }
+ else if (view_mode == VMODE_EXPERT)
+ {
+ Histable *hist = CallStack::getStackPC (user_stack, 0);
+ if (hist->get_type () == Histable::INSTR)
+ {
+ DbeInstr *instr = (DbeInstr*) hist;
+ if (instr->func == dbeSession->get_JUnknown_Function ())
+ return nat_stack;
+ }
+ else if (hist->get_type () == Histable::LINE)
+ {
+ DbeLine *line = (DbeLine *) hist;
+ if (line->func == dbeSession->get_JUnknown_Function ())
+ return nat_stack;
+ }
+ }
+ return user_stack;
+}
+
+Histable *
+CommonPacket::getStackPC (int n, VMode view_mode)
+{
+ return CallStack::getStackPC (getStack (view_mode), n);
+}
+
+Vector<Histable*> *
+CommonPacket::getStackPCs (VMode view_mode)
+{
+ return CallStack::getStackPCs (getStack (view_mode));
+}
+
+void *
+getStack (VMode view_mode, DataView *dview, long idx)
+{
+ void *stack = NULL;
+ if (view_mode == VMODE_MACHINE)
+ stack = dview->getObjValue (PROP_MSTACK, idx);
+ else if (view_mode == VMODE_USER)
+ stack = dview->getObjValue (PROP_USTACK, idx);
+ else if (view_mode == VMODE_EXPERT)
+ stack = dview->getObjValue (PROP_XSTACK, idx);
+ return stack;
+}
+
+int
+stackSize (VMode view_mode, DataView *dview, long idx)
+{
+ return CallStack::stackSize (getStack (view_mode, dview, idx));
+}
+
+Histable *
+getStackPC (int n, VMode view_mode, DataView *dview, long idx)
+{
+ return CallStack::getStackPC (getStack (view_mode, dview, idx), n);
+}
+
+Vector<Histable*> *
+getStackPCs (VMode view_mode, DataView *dview, long idx)
+{
+ return CallStack::getStackPCs (getStack (view_mode, dview, idx));
+}