xref: /netbsd-src/external/gpl3/binutils/dist/gprofng/src/Exp_Layout.cc (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
2    Contributed by Oracle.
3 
4    This file is part of GNU Binutils.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20 
21 #include "config.h"
22 #include "CallStack.h"
23 #include "DbeSession.h"
24 #include "Exp_Layout.h"
25 #include "Experiment.h"
26 #include "Function.h"
27 #include "Table.h"
28 #include "dbe_types.h"
29 #include "util.h"
30 
31 /*
32  * PrUsage is a class which wraps access to the values of prusage
33  * system structure. It was expanded to 64 bit entities in 2.7
34  * (experiment version 6 & 7).
35  */
PrUsage()36 PrUsage::PrUsage ()
37 {
38   pr_tstamp = pr_create = pr_term = pr_rtime = (hrtime_t) 0;
39   pr_utime = pr_stime = pr_ttime = pr_tftime = pr_dftime = (hrtime_t) 0;
40   pr_kftime = pr_ltime = pr_slptime = pr_wtime = pr_stoptime = (hrtime_t) 0;
41 
42   pr_minf = pr_majf = pr_nswap = pr_inblk = pr_oublk = 0;
43   pr_msnd = pr_mrcv = pr_sigs = pr_vctx = pr_ictx = pr_sysc = pr_ioch = 0;
44 }
45 
46 /*
47  * Resource usage.  /proc/<pid>/usage /proc/<pid>/lwp/<lwpid>/lwpusage
48  */
49 struct timestruc_32
50 { /* v8 timestruc_t */
51   uint32_t tv_sec;              /* seconds */
52   uint32_t tv_nsec;             /* and nanoseconds */
53 };
54 
55 typedef struct ana_prusage
56 {
57   id_t pr_lwpid;                /* lwp id.  0: process or defunct */
58   int pr_count;                 /* number of contributing lwps */
59   timestruc_32 pr_tstamp;       /* current time stamp */
60   timestruc_32 pr_create;       /* process/lwp creation time stamp */
61   timestruc_32 pr_term;         /* process/lwp termination time stamp */
62   timestruc_32 pr_rtime;        /* total lwp real (elapsed) time */
63   timestruc_32 pr_utime;        /* user level cpu time */
64   timestruc_32 pr_stime;        /* system call cpu time */
65   timestruc_32 pr_ttime;        /* other system trap cpu time */
66   timestruc_32 pr_tftime;       /* text page fault sleep time */
67   timestruc_32 pr_dftime;       /* data page fault sleep time */
68   timestruc_32 pr_kftime;       /* kernel page fault sleep time */
69   timestruc_32 pr_ltime;        /* user lock wait sleep time */
70   timestruc_32 pr_slptime;      /* all other sleep time */
71   timestruc_32 pr_wtime;        /* wait-cpu (latency) time */
72   timestruc_32 pr_stoptime;     /* stopped time */
73   timestruc_32 filltime[6];     /* filler for future expansion */
74   uint32_t pr_minf;             /* minor page faults */
75   uint32_t pr_majf;             /* major page faults */
76   uint32_t pr_nswap;            /* swaps */
77   uint32_t pr_inblk;            /* input blocks */
78   uint32_t pr_oublk;            /* output blocks */
79   uint32_t pr_msnd;             /* messages sent */
80   uint32_t pr_mrcv;             /* messages received */
81   uint32_t pr_sigs;             /* signals received */
82   uint32_t pr_vctx;             /* voluntary context switches */
83   uint32_t pr_ictx;             /* involuntary context switches */
84   uint32_t pr_sysc;             /* system calls */
85   uint32_t pr_ioch;             /* chars read and written */
86   uint32_t filler[10];          /* filler for future expansion */
87 } raw_prusage_32;
88 
89 uint64_t
bind32Size()90 PrUsage::bind32Size ()
91 {
92   uint64_t bindSize = sizeof (raw_prusage_32);
93   return bindSize;
94 }
95 
96 #define timestruc2hr(x) ((hrtime_t)(x).tv_sec*NANOSEC + (hrtime_t)(x).tv_nsec)
97 
98 PrUsage *
bind32(void * p,bool need_swap_endian)99 PrUsage::bind32 (void *p, bool need_swap_endian)
100 {
101   if (p == NULL)
102     return NULL;
103   raw_prusage_32 pu, *tmp = (raw_prusage_32*) p;
104   if (need_swap_endian)
105     {
106       pu = *tmp;
107       tmp = &pu;
108       SWAP_ENDIAN (pu.pr_tstamp.tv_sec);
109       SWAP_ENDIAN (pu.pr_tstamp.tv_nsec);
110       SWAP_ENDIAN (pu.pr_create.tv_sec);
111       SWAP_ENDIAN (pu.pr_create.tv_nsec);
112       SWAP_ENDIAN (pu.pr_term.tv_sec);
113       SWAP_ENDIAN (pu.pr_term.tv_nsec);
114       SWAP_ENDIAN (pu.pr_rtime.tv_sec);
115       SWAP_ENDIAN (pu.pr_rtime.tv_nsec);
116       SWAP_ENDIAN (pu.pr_utime.tv_sec);
117       SWAP_ENDIAN (pu.pr_utime.tv_nsec);
118       SWAP_ENDIAN (pu.pr_stime.tv_sec);
119       SWAP_ENDIAN (pu.pr_stime.tv_nsec);
120       SWAP_ENDIAN (pu.pr_ttime.tv_sec);
121       SWAP_ENDIAN (pu.pr_ttime.tv_nsec);
122       SWAP_ENDIAN (pu.pr_tftime.tv_sec);
123       SWAP_ENDIAN (pu.pr_tftime.tv_nsec);
124       SWAP_ENDIAN (pu.pr_dftime.tv_sec);
125       SWAP_ENDIAN (pu.pr_dftime.tv_nsec);
126       SWAP_ENDIAN (pu.pr_kftime.tv_sec);
127       SWAP_ENDIAN (pu.pr_kftime.tv_nsec);
128       SWAP_ENDIAN (pu.pr_ltime.tv_sec);
129       SWAP_ENDIAN (pu.pr_ltime.tv_nsec);
130       SWAP_ENDIAN (pu.pr_slptime.tv_sec);
131       SWAP_ENDIAN (pu.pr_slptime.tv_nsec);
132       SWAP_ENDIAN (pu.pr_wtime.tv_sec);
133       SWAP_ENDIAN (pu.pr_wtime.tv_nsec);
134       SWAP_ENDIAN (pu.pr_stoptime.tv_sec);
135       SWAP_ENDIAN (pu.pr_stoptime.tv_nsec);
136       SWAP_ENDIAN (pu.pr_minf);
137       SWAP_ENDIAN (pu.pr_majf);
138       SWAP_ENDIAN (pu.pr_nswap);
139       SWAP_ENDIAN (pu.pr_inblk);
140       SWAP_ENDIAN (pu.pr_oublk);
141       SWAP_ENDIAN (pu.pr_msnd);
142       SWAP_ENDIAN (pu.pr_mrcv);
143       SWAP_ENDIAN (pu.pr_sigs);
144       SWAP_ENDIAN (pu.pr_vctx);
145       SWAP_ENDIAN (pu.pr_ictx);
146       SWAP_ENDIAN (pu.pr_sysc);
147       SWAP_ENDIAN (pu.pr_ioch);
148     }
149   pr_tstamp = timestruc2hr (tmp->pr_tstamp);
150   pr_create = timestruc2hr (tmp->pr_create);
151   pr_term = timestruc2hr (tmp->pr_term);
152   pr_rtime = timestruc2hr (tmp->pr_rtime);
153   pr_utime = timestruc2hr (tmp->pr_utime);
154   pr_stime = timestruc2hr (tmp->pr_stime);
155   pr_ttime = timestruc2hr (tmp->pr_ttime);
156   pr_tftime = timestruc2hr (tmp->pr_tftime);
157   pr_dftime = timestruc2hr (tmp->pr_dftime);
158   pr_kftime = timestruc2hr (tmp->pr_kftime);
159   pr_ltime = timestruc2hr (tmp->pr_ltime);
160   pr_slptime = timestruc2hr (tmp->pr_slptime);
161   pr_wtime = timestruc2hr (tmp->pr_wtime);
162   pr_stoptime = timestruc2hr (tmp->pr_stoptime);
163   pr_minf = tmp->pr_minf;
164   pr_majf = tmp->pr_majf;
165   pr_nswap = tmp->pr_nswap;
166   pr_inblk = tmp->pr_inblk;
167   pr_oublk = tmp->pr_oublk;
168   pr_msnd = tmp->pr_msnd;
169   pr_mrcv = tmp->pr_mrcv;
170   pr_sigs = tmp->pr_sigs;
171   pr_vctx = tmp->pr_vctx;
172   pr_ictx = tmp->pr_ictx;
173   pr_sysc = tmp->pr_sysc;
174   pr_ioch = tmp->pr_ioch;
175   return this;
176 }
177 
178 struct timestruc_64
179 { /* 64-bit timestruc_t */
180   uint64_t tv_sec;          /* seconds */
181   uint64_t tv_nsec;         /* and nanoseconds */
182 };
183 
184 typedef struct
185 {
186   id_t pr_lwpid;            /* lwp id.  0: process or defunct */
187   int pr_count;             /* number of contributing lwps */
188   timestruc_64 pr_tstamp;   /* current time stamp */
189   timestruc_64 pr_create;   /* process/lwp creation time stamp */
190   timestruc_64 pr_term;     /* process/lwp termination time stamp */
191   timestruc_64 pr_rtime;    /* total lwp real (elapsed) time */
192   timestruc_64 pr_utime;    /* user level cpu time */
193   timestruc_64 pr_stime;    /* system call cpu time */
194   timestruc_64 pr_ttime;    /* other system trap cpu time */
195   timestruc_64 pr_tftime;   /* text page fault sleep time */
196   timestruc_64 pr_dftime;   /* data page fault sleep time */
197   timestruc_64 pr_kftime;   /* kernel page fault sleep time */
198   timestruc_64 pr_ltime;    /* user lock wait sleep time */
199   timestruc_64 pr_slptime;  /* all other sleep time */
200   timestruc_64 pr_wtime;    /* wait-cpu (latency) time */
201   timestruc_64 pr_stoptime; /* stopped time */
202   timestruc_64 filltime[6]; /* filler for future expansion */
203   uint64_t pr_minf;         /* minor page faults */
204   uint64_t pr_majf;         /* major page faults */
205   uint64_t pr_nswap;        /* swaps */
206   uint64_t pr_inblk;        /* input blocks */
207   uint64_t pr_oublk;        /* output blocks */
208   uint64_t pr_msnd;         /* messages sent */
209   uint64_t pr_mrcv;         /* messages received */
210   uint64_t pr_sigs;         /* signals received */
211   uint64_t pr_vctx;         /* voluntary context switches */
212   uint64_t pr_ictx;         /* involuntary context switches */
213   uint64_t pr_sysc;         /* system calls */
214   uint64_t pr_ioch;         /* chars read and written */
215   uint64_t filler[10];      /* filler for future expansion */
216 } raw_prusage_64;
217 
218 uint64_t
bind64Size()219 PrUsage::bind64Size ()
220 {
221   uint64_t bindSize = sizeof (raw_prusage_64);
222   return bindSize;
223 }
224 
225 PrUsage *
bind64(void * p,bool need_swap_endian)226 PrUsage::bind64 (void *p, bool need_swap_endian)
227 {
228   if (p == NULL)
229     {
230       return NULL;
231     }
232   raw_prusage_64 pu, *tmp = (raw_prusage_64*) p;
233   if (need_swap_endian)
234     {
235       pu = *tmp;
236       tmp = &pu;
237       SWAP_ENDIAN (pu.pr_tstamp.tv_sec);
238       SWAP_ENDIAN (pu.pr_tstamp.tv_nsec);
239       SWAP_ENDIAN (pu.pr_create.tv_sec);
240       SWAP_ENDIAN (pu.pr_create.tv_nsec);
241       SWAP_ENDIAN (pu.pr_term.tv_sec);
242       SWAP_ENDIAN (pu.pr_term.tv_nsec);
243       SWAP_ENDIAN (pu.pr_rtime.tv_sec);
244       SWAP_ENDIAN (pu.pr_rtime.tv_nsec);
245       SWAP_ENDIAN (pu.pr_utime.tv_sec);
246       SWAP_ENDIAN (pu.pr_utime.tv_nsec);
247       SWAP_ENDIAN (pu.pr_stime.tv_sec);
248       SWAP_ENDIAN (pu.pr_stime.tv_nsec);
249       SWAP_ENDIAN (pu.pr_ttime.tv_sec);
250       SWAP_ENDIAN (pu.pr_ttime.tv_nsec);
251       SWAP_ENDIAN (pu.pr_tftime.tv_sec);
252       SWAP_ENDIAN (pu.pr_tftime.tv_nsec);
253       SWAP_ENDIAN (pu.pr_dftime.tv_sec);
254       SWAP_ENDIAN (pu.pr_dftime.tv_nsec);
255       SWAP_ENDIAN (pu.pr_kftime.tv_sec);
256       SWAP_ENDIAN (pu.pr_kftime.tv_nsec);
257       SWAP_ENDIAN (pu.pr_ltime.tv_sec);
258       SWAP_ENDIAN (pu.pr_ltime.tv_nsec);
259       SWAP_ENDIAN (pu.pr_slptime.tv_sec);
260       SWAP_ENDIAN (pu.pr_slptime.tv_nsec);
261       SWAP_ENDIAN (pu.pr_wtime.tv_sec);
262       SWAP_ENDIAN (pu.pr_wtime.tv_nsec);
263       SWAP_ENDIAN (pu.pr_stoptime.tv_sec);
264       SWAP_ENDIAN (pu.pr_stoptime.tv_nsec);
265       SWAP_ENDIAN (pu.pr_minf);
266       SWAP_ENDIAN (pu.pr_majf);
267       SWAP_ENDIAN (pu.pr_nswap);
268       SWAP_ENDIAN (pu.pr_inblk);
269       SWAP_ENDIAN (pu.pr_oublk);
270       SWAP_ENDIAN (pu.pr_msnd);
271       SWAP_ENDIAN (pu.pr_mrcv);
272       SWAP_ENDIAN (pu.pr_sigs);
273       SWAP_ENDIAN (pu.pr_vctx);
274       SWAP_ENDIAN (pu.pr_ictx);
275       SWAP_ENDIAN (pu.pr_sysc);
276       SWAP_ENDIAN (pu.pr_ioch);
277     }
278 
279   pr_tstamp = timestruc2hr (tmp->pr_tstamp);
280   pr_create = timestruc2hr (tmp->pr_create);
281   pr_term = timestruc2hr (tmp->pr_term);
282   pr_rtime = timestruc2hr (tmp->pr_rtime);
283   pr_utime = timestruc2hr (tmp->pr_utime);
284   pr_stime = timestruc2hr (tmp->pr_stime);
285   pr_ttime = timestruc2hr (tmp->pr_ttime);
286   pr_tftime = timestruc2hr (tmp->pr_tftime);
287   pr_dftime = timestruc2hr (tmp->pr_dftime);
288   pr_kftime = timestruc2hr (tmp->pr_kftime);
289   pr_ltime = timestruc2hr (tmp->pr_ltime);
290   pr_slptime = timestruc2hr (tmp->pr_slptime);
291   pr_wtime = timestruc2hr (tmp->pr_wtime);
292   pr_stoptime = timestruc2hr (tmp->pr_stoptime);
293   pr_minf = tmp->pr_minf;
294   pr_majf = tmp->pr_majf;
295   pr_nswap = tmp->pr_nswap;
296   pr_inblk = tmp->pr_inblk;
297   pr_oublk = tmp->pr_oublk;
298   pr_msnd = tmp->pr_msnd;
299   pr_mrcv = tmp->pr_mrcv;
300   pr_sigs = tmp->pr_sigs;
301   pr_vctx = tmp->pr_vctx;
302   pr_ictx = tmp->pr_ictx;
303   pr_sysc = tmp->pr_sysc;
304   pr_ioch = tmp->pr_ioch;
305   return this;
306 }
307 
308 Vector<long long> *
getMstateValues()309 PrUsage::getMstateValues ()
310 {
311   const PrUsage *prusage = this;
312   Vector<long long> *states = new Vector<long long>;
313   states->store (0, prusage->pr_utime);
314   states->store (1, prusage->pr_stime);
315   states->store (2, prusage->pr_ttime);
316   states->store (3, prusage->pr_tftime);
317   states->store (4, prusage->pr_dftime);
318   states->store (5, prusage->pr_kftime);
319   states->store (6, prusage->pr_ltime);
320   states->store (7, prusage->pr_slptime);
321   states->store (8, prusage->pr_wtime);
322   states->store (9, prusage->pr_stoptime);
323   assert (LMS_NUM_SOLARIS_MSTATES == states->size ());
324   return states;
325 }
326 
327 void* CommonPacket::jvm_overhead = NULL;
328 
CommonPacket()329 CommonPacket::CommonPacket ()
330 {
331   for (int i = 0; i < NTAGS; i++)
332     tags[i] = 0;
333   tstamp = 0;
334   jthread_TBR = NULL;
335   frinfo = 0;
336   leafpc = 0;
337   nat_stack = NULL;
338   user_stack = NULL;
339 }
340 
341 int
cmp(const void * a,const void * b)342 CommonPacket::cmp (const void *a, const void *b)
343 {
344   if ((*(CommonPacket **) a)->tstamp > (*(CommonPacket **) b)->tstamp)
345     return 1;
346   else if ((*(CommonPacket **) a)->tstamp < (*(CommonPacket **) b)->tstamp)
347     return -1;
348   else
349     return 0;
350 }
351 
352 void *
getStack(VMode view_mode)353 CommonPacket::getStack (VMode view_mode)
354 {
355   if (view_mode == VMODE_MACHINE)
356     return nat_stack;
357   else if (view_mode == VMODE_USER)
358     {
359       if (jthread_TBR == JTHREAD_NONE || (jthread_TBR && jthread_TBR->is_system ()))
360 	return jvm_overhead;
361     }
362   else if (view_mode == VMODE_EXPERT)
363     {
364       Histable *hist = CallStack::getStackPC (user_stack, 0);
365       if (hist->get_type () == Histable::INSTR)
366 	{
367 	  DbeInstr *instr = (DbeInstr*) hist;
368 	  if (instr->func == dbeSession->get_JUnknown_Function ())
369 	    return nat_stack;
370 	}
371       else if (hist->get_type () == Histable::LINE)
372 	{
373 	  DbeLine *line = (DbeLine *) hist;
374 	  if (line->func == dbeSession->get_JUnknown_Function ())
375 	    return nat_stack;
376 	}
377     }
378   return user_stack;
379 }
380 
381 Histable *
getStackPC(int n,VMode view_mode)382 CommonPacket::getStackPC (int n, VMode view_mode)
383 {
384   return CallStack::getStackPC (getStack (view_mode), n);
385 }
386 
387 Vector<Histable*> *
getStackPCs(VMode view_mode)388 CommonPacket::getStackPCs (VMode view_mode)
389 {
390   return CallStack::getStackPCs (getStack (view_mode));
391 }
392 
393 void *
getStack(VMode view_mode,DataView * dview,long idx)394 getStack (VMode view_mode, DataView *dview, long idx)
395 {
396   void *stack = NULL;
397   if (view_mode == VMODE_MACHINE)
398     stack = dview->getObjValue (PROP_MSTACK, idx);
399   else if (view_mode == VMODE_USER)
400     stack = dview->getObjValue (PROP_USTACK, idx);
401   else if (view_mode == VMODE_EXPERT)
402     stack = dview->getObjValue (PROP_XSTACK, idx);
403   return stack;
404 }
405 
406 int
stackSize(VMode view_mode,DataView * dview,long idx)407 stackSize (VMode view_mode, DataView *dview, long idx)
408 {
409   return CallStack::stackSize (getStack (view_mode, dview, idx));
410 }
411 
412 Histable *
getStackPC(int n,VMode view_mode,DataView * dview,long idx)413 getStackPC (int n, VMode view_mode, DataView *dview, long idx)
414 {
415   return CallStack::getStackPC (getStack (view_mode, dview, idx), n);
416 }
417 
418 Vector<Histable*> *
getStackPCs(VMode view_mode,DataView * dview,long idx)419 getStackPCs (VMode view_mode, DataView *dview, long idx)
420 {
421   return CallStack::getStackPCs (getStack (view_mode, dview, idx));
422 }
423