1
## ``The contents of this file are subject to the Erlang Public License,
2
## Version 1.1, (the "License"); you may not use this file except in
3
## compliance with the License. You should have received a copy of the
4
## Erlang Public License along with this software. If not, it can be
5
## retrieved via the world wide web at http://www.erlang.org/.
7
## Software distributed under the License is distributed on an "AS IS"
8
## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
## the License for the specific language governing rights and limitations
12
## The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
## Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
## AB. All Rights Reserved.''
18
############################################################################
27
%---------------------------------------------------------------------------
30
% Same as "help etp-help"
32
% Emulator Toolbox for Pathologists
33
% - GDB commad toolbox for analyzing core dumps form the
34
% Erlang emulator (BEAM).
36
% Should work for 32-bit erts-5.2/R9B, ...
38
% The commands are prefixed with:
39
% etp: Acronym for erts-term-print
40
% etpf: Acronym for erts-term-print-flat
42
% User commands (these have help themselves):
47
% Useful for doing step-by-step traversal of lists and tuples after
48
% calling the toplevel command etpf:
49
% etpf-cons, etpf-boxed,
51
% Special commands for not really terms:
53
% etp-msgq, etpf-msgq,
54
% etp-stacktrace, etp-stackdump, etpf-stackdump, etp-dictdump
55
% etp-offheapdump, etpf-offheapdump,
56
% etp-search-heaps, etp-search-alloc,
57
% etp-ets-tables, etp-ets-tabledump
59
% Complex commands that use the Erlang support module.
60
% etp-overlapped-heaps, etp-chart, etp-chart-start, etp-chart-end
62
% Erlang support module handling commands:
65
% Parameter handling commands:
66
% etp-show, etp-set-max-depth, etp-set-max-string-length
68
% Other commands you may find in this toolbox are suffixed -1, -2, ...
69
% and are internal; not for the console user.
71
% The Erlang support module requires `erl' and `erlc' in the path.
72
% The compiled "erl_commands.beam" file is stored in the current
73
% working directory, so it is thereby in the search path of `erl'.
75
% These are just helpful commands when analyzing core dumps, but
76
% you will not get away without knowing the gory details of the
77
% tag bits. Do not forget about the e.g p, p/x, x and x/4x commands.
79
% Execution speed of user defined gdb commands is not lightning fast.
80
% It may well take half a minute do dump a complex term with the default
81
% max depth values on our old Sparc Ultra-10's.
83
% To use the Erlang support module, the environment variable ROOTDIR
84
% must be set to the toplevel installation directory of Erlang/OTP,
85
% so the etp-commands file becomes:
86
% $ROOTDIR/erts/etc/unix/etp-commands
87
% Also, erl and erlc must be in the path.
88
%---------------------------------------------------------------------------
91
############################################################################
100
etp-1 ((Eterm)($arg0)) 0
105
%---------------------------------------------------------------------------
108
% Takes a toplevel Erlang term and prints the whole deep term
109
% very much as in Erlang itself. Up to a max depth. See etp-show.
110
%---------------------------------------------------------------------------
114
# Args: Eterm, int depth
118
if (($arg0) & 0x3) == 1
121
printf "<etpf-cons %#x>", ($arg0)
123
etp-list-1 ($arg0) ($arg1)
126
if (($arg0) & 0x3) == 2
128
printf "<etpf-boxed %#x>", ($arg0)
130
etp-boxed-1 ($arg0) ($arg1)
133
if (($arg0) & 0x3) == 3
134
etp-immediate-1 ($arg0)
136
# (($arg0) & 0x3) == 0
138
printf "<the non-value>"
141
printf "<the non-value debug>"
156
etp-1 ((Eterm)($arg0))
162
%---------------------------------------------------------------------------
165
% Takes a toplevel Erlang term and prints it is. If it is a deep term
166
% print which command to use to traverse down one level.
167
%---------------------------------------------------------------------------
170
############################################################################
171
# Commands for nested terms. Some are recursive.
175
# Args: Eterm cons_cell, int depth
179
if (($arg0) & 0x3) != 0x1
180
printf "#NotCons<%#x>", ($arg0)
184
etp-chart-entry-1 ($arg0) ($arg1) 2
186
etp-list-printable-1 ($arg0) ($arg1)
187
if !$etp_list_printable
190
etp-list-2 ($arg0) (($arg1)+1)
195
define etp-list-printable-1
196
# Args: Eterm list, int depth
200
# Returns: $etp_list_printable
202
if (($arg0) & 0x3) != 0x1
203
printf "#NotCons<%#x>", ($arg0)
205
# Loop to check if it is a printable string
206
set $etp_list_p = ($arg0)
207
set $etp_list_printable = ($etp_list_p != $etp_nil)
209
while ($etp_list_p != $etp_nil) && \
210
($etp_list_i < $etp_max_string_length) && \
212
if ($etp_list_p & 0x3) == 0x1
214
set $etp_list_n = ((Eterm*)($etp_list_p & ~0x3))[0]
215
if ($etp_list_n & 0xF) == 0xF
216
etp-ct-printable-1 ($etp_list_n>>4)
219
set $etp_list_p = ((Eterm*)($etp_list_p & ~0x3))[1]
222
set $etp_list_printable = 0
225
set $etp_list_printable = 0
228
set $etp_list_printable = 0
232
if $etp_list_printable
233
# Print printable string
235
set $etp_list_p = ($arg0)
237
while $etp_list_p != $etp_nil
238
set $etp_list_n = ((Eterm*)($etp_list_p & ~0x3))[0]
239
etp-char-1 ($etp_list_n>>4) '"'
240
set $etp_list_p = ((Eterm*)($etp_list_p & ~0x3))[1]
242
if $etp_list_p == $etp_nil
245
if $etp_list_i >= $etp_max_string_length
246
set $etp_list_p = $etp_nil
250
etp-chart-entry-1 ($arg0) (($arg1)+$etp_list_i) 2
260
# Args: Eterm cons_cell, int depth
264
if (($arg0) & 0x3) != 0x1
265
printf "#NotCons<%#x>", ($arg0)
268
if ($arg1) >= $etp_max_depth
271
etp-1 (((Eterm*)(($arg0)&~0x3))[0]) (($arg1)+1)
272
if ((Eterm*)(($arg0) & ~0x3))[1] == $etp_nil
277
etp-chart-entry-1 ($arg0) ($arg1) 2
279
if (((Eterm*)(($arg0)&~0x3))[1]&0x3) == 0x1
282
etp-list-2 (((Eterm*)(($arg0)&~0x3))[1]) (($arg1)+1)
286
etp-1 (((Eterm*)(($arg0)&~0x3))[1]) (($arg1)+1)
299
if ((Eterm)($arg0) & 0x3) != 0x1
300
printf "#NotCons<%#x>", ($arg0)
305
etp-1 (((Eterm*)((Eterm)($arg0)&~0x3))[0])
307
etp-1 (((Eterm*)((Eterm)($arg0)&~0x3))[1])
314
%---------------------------------------------------------------------------
317
% Takes a Cons ptr and prints the Car and Cdr cells with etpf (flat).
318
%---------------------------------------------------------------------------
324
# Args: Eterm, int depth
328
if (($arg0) & 0x3) != 0x2
329
printf "#NotBoxed<%#x>", ($arg0)
331
if (((Eterm*)(($arg0) & ~0x3))[0] & 0x3) != 0x0
333
etp-chart-entry-1 (($arg0)&~0x3) ($arg1) 1
335
printf "#BoxedError<%#x>", ($arg0)
338
etp-chart-entry-1 (($arg0)&~0x3) ($arg1) \
339
((((Eterm*)(($arg0)&~0x3))[0]>>6)+1)
341
if (((Eterm*)(($arg0) & ~0x3))[0] & 0x3f) == 0x0
343
etp-array-1 ((Eterm*)(($arg0)&~0x3)) ($arg1) ($arg1) \
344
1 ((((Eterm*)(($arg0)&~0x3))[0]>>6)+1) '}'
346
etp-boxed-immediate-1 ($arg0)
352
define etp-boxed-immediate-1
353
# Args: Eterm, int depth
357
if (($arg0) & 0x3) != 0x2
358
printf "#NotBoxed<%#x>", ($arg0)
360
if (((Eterm*)(($arg0) & ~0x3))[0] & 0x3) != 0x0
361
printf "#BoxedError<%#x>", ($arg0)
363
set $etp_boxed_immediate_p = (Eterm*)(($arg0) & ~0x3)
364
set $etp_boxed_immediate_h = ($etp_boxed_immediate_p[0] >> 2) & 0xF
365
if $etp_boxed_immediate_h == 0xC
368
if $etp_boxed_immediate_h == 0xD
369
etp-extport-1 ($arg0)
371
if ($etp_boxed_immediate_h == 0x2) || \
372
($etp_boxed_immediate_h == 0x3)
375
if ($etp_boxed_immediate_h == 0x6)
378
if ($etp_boxed_immediate_h == 0x4)
381
if ($etp_boxed_immediate_h == 0xE)
385
if ($etp_boxed_immediate_h == 0x5)
388
if ($etp_boxed_immediate_h == 0x8)
389
printf "#RefcBinary<"
391
if ($etp_boxed_immediate_h == 0x9)
392
printf "#HeapBinary<"
394
if ($etp_boxed_immediate_h == 0xA)
397
printf "#Header%X<", $etp_boxed_immediate_h
402
set $etp_boxed_immediate_arity = $etp_boxed_immediate_p[0]>>6
403
while $etp_boxed_immediate_arity > 0
404
set $etp_boxed_immediate_p++
405
if $etp_boxed_immediate_arity > 1
406
printf "%#x,", *$etp_boxed_immediate_p
408
printf "%#x", *$etp_boxed_immediate_p
409
if ($etp_boxed_immediate_h == 0xA)
410
set $etp_boxed_immediate_p++
411
printf ":%#x", *$etp_boxed_immediate_p
415
set $etp_boxed_immediate_arity--
434
etp-boxed-1 ((Eterm)($arg0)) 0
440
%---------------------------------------------------------------------------
443
% Take a Boxed ptr and print the contents in one level using etpf (flat).
444
%---------------------------------------------------------------------------
450
# Args: Eterm* p, int depth, int width, int pos, int size, int end_char
455
if (($arg1) < $etp_max_depth) && (($arg2) < $etp_max_depth)
456
etp-1 (($arg0)[($arg3)]) (($arg1)+1)
457
if (($arg3) + 1) != ($arg4)
460
etp-array-1 ($arg0) ($arg1) (($arg2)+1) (($arg3)+1) ($arg4) ($arg5)
462
printf "...%c", ($arg5)
472
## Args: Eterm, int depth, int index, int arity
476
# if ($arg1) >= $etp_max_depth+$etp_max_string_length
477
# printf "%% Max depth for term %d\n", $etp_chart_id
479
# if ($arg2) < ($arg3)
480
# etp-1 (((Eterm*)(($arg0)&~0x3))[$arg2]) (($arg1)+1)
481
# etpa-1 ($arg0) (($arg1)+1) (($arg2)+1) ($arg3)
486
############################################################################
487
# Commands for non-nested terms. Recursion leaves. Some call other leaves.
490
define etp-immediate-1
495
if (($arg0) & 0x3) != 0x3
496
printf "#NotImmediate<%#x>", ($arg0)
498
if (($arg0) & 0xF) == 0x3
501
if (($arg0) & 0xF) == 0x7
504
if (($arg0) & 0xF) == 0xf
506
printf "%d", ($arg0)>>4
509
if (($arg0) & 0x3f) == 0x0b
512
if (($arg0) & 0x3f) == 0x1b
513
printf "#Catch<%d>", ($arg0)>>6
515
if (($arg0) == $etp_nil)
518
printf "#UnknownImmediate<%#x>", ($arg0)
535
if ((Eterm)($arg0) & 0x3f) != 0xb
536
printf "#NotAtom<%#x>", ($arg0)
538
set $etp_atom_1_ap = (Atom*)erts_atom_table.seg_table[(Eterm)($arg0)>>16][((Eterm)($arg0)>>6)&0x3FF]
539
set $etp_atom_1_i = ($etp_atom_1_ap)->len
540
set $etp_atom_1_p = ($etp_atom_1_ap)->name
541
set $etp_atom_1_quote = 1
542
# Check if atom has to be quoted
543
if ($etp_atom_1_i > 0)
544
etp-ct-atom-1 (*$etp_atom_1_p)
546
# Atom start character
549
set $etp_atom_1_quote = 0
551
set $etp_atom_1_i = 0
554
while $etp_atom_1_i > 0
555
etp-ct-name-1 (*$etp_atom_1_p)
561
set $etp_atom_1_quote = 1
562
set $etp_atom_1_i = 0
569
set $etp_atom_1_i = ($etp_atom_1_ap)->len
570
set $etp_atom_1_p = ($etp_atom_1_ap)->name
571
while $etp_atom_1_i > 0
572
etp-char-1 (*$etp_atom_1_p) '\''
585
# Args: int char, int quote_char
589
if (($arg0) < 0) || (0377 < ($arg0))
590
printf "#NotChar<%#x>", ($arg0)
592
if ($arg0) == ($arg1)
593
printf "\\%c", ($arg0)
595
etp-ct-printable-1 ($arg0)
597
if $etp_ct_printable < 0
600
printf "\\%c", $etp_ct_printable
603
printf "\\%03o", ($arg0)
609
define etp-ct-printable-1
612
# Determines if integer is a printable character
615
# Returns: $etp_ct_printable
616
# escape alias char, or -1 if no escape alias
618
set $etp_ct_printable = 'b'
621
set $etp_ct_printable = 't'
624
set $etp_ct_printable = 'n'
627
set $etp_ct_printable = 'v'
630
set $etp_ct_printable = 'f'
633
set $etp_ct_printable = 'e'
635
if ((040 <= ($arg0)) && (($arg0) <= 0176)) || \
636
((0240 <= ($arg0)) && (($arg0) <= 0377))
637
# Other printable character
638
set $etp_ct_printable = -1
640
set $etp_ct_printable = 0
653
# Determines if integer is a atom first character
656
# Returns: $etp_ct_atom
657
if ((0141 <= ($arg0)) && (($arg0) <= 0172)) || \
658
((0337 <= ($arg0)) && (($arg0) != 0367) && (($arg0) <= 0377))
659
# Atom start character
666
define etp-ct-variable-1
669
# Determines if integer is a variable first character
672
# Returns: $etp_ct_variable
673
if ((056 == ($arg0)) || \
674
(0101 <= ($arg0)) && (($arg0) <= 0132)) || \
675
(0137 == ($arg0)) || \
676
((0300 <= ($arg0)) && (($arg0) != 0327) && (($arg0) <= 0336))
677
# Variable start character
678
set $etp_ct_variable = 1
680
set $etp_ct_variable = 0
687
# Determines if integer is a name character,
688
# i.e non-first atom or variable character.
691
# Returns: $etp_ct_variable
692
if (($arg0) == 0100 || \
693
(060 <= ($arg0)) && (($arg0) <= 071))
696
etp-ct-atom-1 ($arg0)
700
etp-ct-variable-1 ($arg0)
701
set $etp_ct_name = $etp_ct_variable
713
set $etp_pid_1 = (Eterm)($arg0)
714
if ($etp_pid_1 & 0xF) == 0x3
716
printf "<0/%u.%u.%u>", erts_this_node->creation, \
717
($etp_pid_1>>4)&0x7fff, ($etp_pid_1>>19)&0x1fff
719
printf "#NotPid<%#x>", ($arg0)
728
if ((Eterm)($arg0) & 0x3) != 0x2
729
printf "#NotBoxed<%#x>", (Eterm)($arg0)
731
set $etp_extpid_1_p = (ExternalThing*)((Eterm)($arg0) & ~0x3)
732
if ($etp_extpid_1_p->header & 0x3f) != 0x30
733
printf "#NotExternalPid<%#x>", $etp_extpid_1_p->header
736
set $etp_extpid_1_number = $etp_extpid_1_p->data[0]&0x7fff
737
set $etp_extpid_1_serial = ($etp_extpid_1_p->data[0]>>15)&0x1fff
738
set $etp_extpid_1_np = $etp_extpid_1_p->node
739
set $etp_extpid_1_creation = $etp_extpid_1_np->creation
740
set $etp_extpid_1_dep = $etp_extpid_1_np->dist_entry
741
set $etp_extpid_1_node = $etp_extpid_1_np->sysname
742
if ($etp_extpid_1_node & 0x3f) != 0xb
744
printf "#ExternalPidError<%#x>", ($arg0)
746
if $etp_extpid_1_dep == erts_this_dist_entry
749
printf "<%u:", $etp_extpid_1_node>>6
751
etp-atom-1 ($etp_extpid_1_node)
752
printf "/%u.%u.%u>", $etp_extpid_1_creation, \
753
$etp_extpid_1_number, $etp_extpid_1_serial
766
set $etp_port_1 = (Eterm)($arg0)
767
if ($etp_port_1 & 0xF) == 0x7
769
printf "#Port<0/%u.%u>", erts_this_node->creation, \
770
($etp_port_1>>4)&0x3ffff
772
printf "#NotPort<%#x>", ($arg0)
777
# Args: Eterm extport
781
if ((Eterm)($arg0) & 0x3) != 0x2
782
printf "#NotBoxed<%#x>", (Eterm)($arg0)
784
set $etp_extport_1_p = (ExternalThing*)((Eterm)($arg0) & ~0x3)
785
if ($etp_extport_1_p->header & 0x3F) != 0x34
786
printf "#NotExternalPort<%#x>", $etp_extport_1->header
789
set $etp_extport_1_number = $etp_extport_1_p->data[0]&0x3ffff
790
set $etp_extport_1_np = $etp_extport_1_p->node
791
set $etp_extport_1_creation = $etp_extport_1_np->creation
792
set $etp_extport_1_dep = $etp_extport_1_np->dist_entry
793
set $etp_extport_1_node = $etp_extport_1_np->sysname
794
if ($etp_extport_1_node & 0x3f) != 0xb
796
printf "#ExternalPortError<%#x>", ($arg0)
798
if $etp_extport_1_dep == erts_this_dist_entry
801
printf "#Port<%u:", $etp_extport_1_node>>6
803
etp-atom-1 ($etp_extport_1_node)
804
printf "/%u.%u>", $etp_extport_1_creation, $etp_extport_1_number
817
if ((Eterm)($arg0) & 0x3) != 0x2
818
printf "#NotBoxed<%#x>", (Eterm)($arg0)
820
set $etp_bignum_1_p = (Eterm*)((Eterm)($arg0) & ~0x3)
821
if ($etp_bignum_1_p[0] & 0x3b) != 0x08
822
printf "#NotBignum<%#x>", $etp_bignum_1_p[0]
824
set $etp_bignum_1_i = 2 * ($etp_bignum_1_p[0] >> 6)
825
if $etp_bignum_1_i < 2
826
printf "#BignumError<%#x>", (Eterm)($arg0)
828
if $etp_bignum_1_p[0] & 0x04
831
set $etp_bignum_1_p = (unsigned short *)($etp_bignum_1_p + 1)
833
while $etp_bignum_1_i > 0
834
set $etp_bignum_1_i--
835
printf "%04x", $etp_bignum_1_p[$etp_bignum_1_i]
849
if ((Eterm)($arg0) & 0x3) != 0x2
850
printf "#NotBoxed<%#x>", (Eterm)($arg0)
852
set $etp_float_1_p = (Eterm*)((Eterm)($arg0) & ~0x3)
853
if ($etp_float_1_p[0] & 0x3f) != 0x18
854
printf "#NotFloat<%#x>", $etp_float_1_p[0]
856
printf "%f", *(double*)($etp_float_1_p+1)
868
if ((Eterm)($arg0) & 0x3) != 0x2
869
printf "#NotBoxed<%#x>", (Eterm)($arg0)
871
set $etp_ref_1_p = (Eterm*)((Eterm)($arg0) & ~0x3)
872
if ($etp_ref_1_p[0] & 0x3b) != 0x10
873
printf "#NotRef<%#x>", $etp_ref_1_p[0]
875
set $etp_ref_1_i = ($etp_ref_1_p[0] >> 6)
877
while $etp_ref_1_i > 0
878
printf ".%lu", (unsigned long)$etp_ref_1_p[$etp_ref_1_i]
893
if ((Eterm)($arg0) & 0x3) != 0x2
894
printf "#NotBoxed<%#x>", (Eterm)($arg0)
896
set $etp_extref_1_p = (ExternalThing*)((Eterm)($arg0) & ~0x3)
897
if ($etp_extref_1_p->header & 0x3F) != 0x38
898
printf "#NotExternalRef<%#x>", $etp_extref_1->header
901
set $etp_extref_1_i = ($etp_extref_1_p->header >> 6)
902
set $etp_extref_1_np = $etp_extref_1_p->node
903
set $etp_extref_1_creation = $etp_extref_1_np->creation
904
set $etp_extref_1_dep = $etp_extref_1_np->dist_entry
905
set $etp_extref_1_node = $etp_extref_1_np->sysname
906
if ($etp_extref_1_node & 0x3f) != 0xb \
907
|| $etp_extref_1_i < 2
908
# Node should be an atom
909
printf "#ExternalRefError<%#x>", ($arg0)
911
if $etp_extref_1_dep == erts_this_dist_entry
914
printf "#Ref<%u:", $etp_extref_1_node>>6
916
etp-atom-1 ($etp_extref_1_node)
917
printf "/%u", $etp_extref_1_creation
918
set $etp_extref_1_i -= 2
919
while $etp_extref_1_i > 0
920
set $etp_extref_1_i--
922
(unsigned long)$etp_extref_1_p->data[$etp_extref_1_i]
933
# Args: Eterm*, int offset
938
etp-atom-1 (((Eterm*)($arg0))[0])
940
etp-atom-1 (((Eterm*)($arg0))[1])
941
printf "/%d", ((Eterm*)($arg0))[2]
943
printf "+%#x>", ($arg1)
959
%---------------------------------------------------------------------------
962
% Take an Eterm* to an MFA function name entry and print it.
963
% These can be found e.g in the process structure;
964
% process_tab[i]->current and process_tab[i]->initial.
965
%---------------------------------------------------------------------------
975
set $etp_cp = (Eterm)($arg0)
976
set $etp_cp_low = modules
977
set $etp_cp_high = $etp_cp_low + num_loaded_modules
978
set $etp_cp_mid = mid_module
981
while $etp_cp_low < $etp_cp_high
982
if $etp_cp < $etp_cp_mid->start
983
set $etp_cp_high = $etp_cp_mid
985
if $etp_cp > $etp_cp_mid->end
986
set $etp_cp_low = $etp_cp_mid + 1
988
set $etp_cp_p = $etp_cp_low = $etp_cp_high = $etp_cp_mid
991
set $etp_cp_mid = $etp_cp_low + ($etp_cp_high-$etp_cp_low)/2
994
set $etp_cp_low = (Eterm**)($etp_cp_p->start + 8)
995
set $etp_cp_high = $etp_cp_low +$etp_cp_p->start[0]
997
while $etp_cp_low < $etp_cp_high
998
set $etp_cp_mid = $etp_cp_low + ($etp_cp_high-$etp_cp_low)/2
999
if $etp_cp < $etp_cp_mid[0]
1000
set $etp_cp_high = $etp_cp_mid
1002
if $etp_cp < $etp_cp_mid[1]
1003
set $etp_cp_p = $etp_cp_mid[0]+2
1004
set $etp_cp_low = $etp_cp_high = $etp_cp_mid
1006
set $etp_cp_low = $etp_cp_mid + 1
1013
etp-mfa-1 ($etp_cp_p) ($etp_cp-((Eterm)($etp_cp_p-2)))
1015
if $etp_cp == beam_apply+1
1016
printf "#Cp<terminate process normally>"
1018
if *(Eterm*)($etp_cp) == beam_return_trace[0]
1019
if ($etp_cp) == beam_exception_trace
1020
printf "#Cp<exception trace>"
1022
printf "#Cp<return trace>"
1025
if *(Eterm*)($etp_cp) == beam_return_to_trace[0]
1026
printf "#Cp<return to trace>"
1028
printf "#Cp<%#x>", $etp_cp
1045
%---------------------------------------------------------------------------
1048
% Take a code continuation pointer and print
1049
% module, function, arity and offset.
1051
% Code continuation pointers can be found in the process structure e.g
1052
% process_tab[i]->cp and process_tab[i]->i, the second is the
1053
% program counter, which is the same thing as a continuation pointer.
1054
%---------------------------------------------------------------------------
1057
############################################################################
1058
# Commands for special term bunches.
1062
# Args: ErlMessageQueue*
1066
set $etp_msgq = ($arg0)
1067
set $etp_msgq_p = $etp_msgq->first
1068
set $etp_msgq_i = $etp_msgq->len
1069
set $etp_msgq_prev = $etp_msgq->last
1070
printf "%% Message queue (%d):", $etp_msgq_i
1071
if ($etp_msgq_i > 0) && $etp_msgq_p
1076
while ($etp_msgq_i > 0) && $etp_msgq_p
1078
set $etp_msgq_next = $etp_msgq_p->next
1080
etp-1 ($etp_msgq_p->m[0]) 0
1081
if ($etp_msgq_i > 0) && $etp_msgq_next
1087
etp-1 ($etp_msgq_p->m[1]) 0
1088
if $etp_msgq_p == $etp_msgq->save
1093
if ($etp_msgq_i > 0) && $etp_msgq_next
1097
set $etp_msgq_prev = $etp_msgq_p
1098
set $etp_msgq_p = $etp_msgq_next
1101
printf "#MsgQShort<%d>\n", $etp_msgq_i
1104
printf "#MsgQLong<%#lx%p>\n", (unsigned long)$etp_msgq_p
1106
if $etp_msgq_prev != $etp_msgq->last
1107
printf "#MsgQEndError<%#lx%p>\n", (unsigned long)$etp_msgq_prev
1112
%---------------------------------------------------------------------------
1113
% etp-msgq ErlMessageQueue*
1115
% Take an ErlMessageQueue* and print the contents of the message queue.
1116
% Sequential trace tokens are included in comments and
1117
% the current match position in the queue is marked '<='.
1119
% A process's message queue is process_tab[i]->msg.
1120
%---------------------------------------------------------------------------
1136
%---------------------------------------------------------------------------
1137
% etpf-msgq ErlMessageQueue*
1139
% Same as 'etp-msgq' but print the messages using etpf (flat).
1140
%---------------------------------------------------------------------------
1145
define etp-stacktrace
1150
set $etp_stacktrace_p = ($arg0)->stop
1151
set $etp_stacktrace_end = ($arg0)->hend
1152
printf "%% Stacktrace (%u): ", $etp_stacktrace_end-$etp_stacktrace_p
1154
while $etp_stacktrace_p < $etp_stacktrace_end
1155
if ($etp_stacktrace_p[0] & 0x3) == 0x0
1156
# Continuation pointer
1157
etp $etp_stacktrace_p[0]
1159
set $etp_stacktrace_p++
1163
document etp-stacktrace
1164
%---------------------------------------------------------------------------
1165
% etp-stacktrace Process*
1167
% Take an Process* and print a stactrace for the process.
1168
% The stacktrace consists just of the pushed code continuation
1169
% pointers on the stack, the most recently pushed first.
1170
%---------------------------------------------------------------------------
1173
define etp-stackdump
1178
set $etp_stackdump_p = ($arg0)->stop
1179
set $etp_stackdump_end = ($arg0)->hend
1180
printf "%% Stackdump (%u): ", $etp_stackdump_end-$etp_stackdump_p
1182
while $etp_stackdump_p < $etp_stackdump_end
1183
etp $etp_stackdump_p[0]
1184
set $etp_stackdump_p++
1188
document etp-stackdump
1189
%---------------------------------------------------------------------------
1190
% etp-stackdump Process*
1192
% Take an Process* and print a stackdump for the process.
1193
% The stackdump consists of all pushed values on the stack.
1194
% All code continuation pointers are preceeded with a line
1195
% of dashes to make the stack frames more visible.
1196
%---------------------------------------------------------------------------
1199
define etpf-stackdump
1205
etp-stackdump ($arg0)
1209
document etpf-stackdump
1210
%---------------------------------------------------------------------------
1211
% etpf-stackdump Process*
1213
% Same as etp-stackdump but print the values using etpf (flat).
1214
%---------------------------------------------------------------------------
1224
set $etp_dictdump = ($arg0)
1226
set $etp_dictdump_n = \
1227
$etp_dictdump->homeSize + $etp_dictdump->splitPosition
1228
set $etp_dictdump_i = 0
1229
set $etp_dictdump_written = 0
1230
if $etp_dictdump_n > $etp_dictdump->size
1231
set $etp_dictdump_n = $etp_dictdump->size
1233
set $etp_dictdump_cnt = $etp_dictdump->numElements
1234
printf "%% Dictionary (%d):\n[", $etp_dictdump_cnt
1235
while $etp_dictdump_i < $etp_dictdump_n && \
1236
$etp_dictdump_cnt > 0
1237
set $etp_dictdump_p = $etp_dictdump->data[$etp_dictdump_i]
1238
if $etp_dictdump_p != $etp_nil
1239
if ((Eterm)$etp_dictdump_p & 0x3) == 0x2
1241
if $etp_dictdump_written
1244
set $etp_dictdump_written = 1
1246
etp-1 $etp_dictdump_p 0
1247
set $etp_dictdump_cnt--
1249
while ((Eterm)$etp_dictdump_p & 0x3) == 0x1 && \
1250
$etp_dictdump_cnt > 0
1252
if $etp_dictdump_written
1255
set $etp_dictdump_written = 1
1257
etp-1 (((Eterm*)((Eterm)$etp_dictdump_p&~0x3))[0]) 0
1258
set $etp_dictdump_cnt--
1259
set $etp_dictdump_p = ((Eterm*)((Eterm)$etp_dictdump_p & ~0x3))[1]
1261
if $etp_dictdump_p != $etp_nil
1262
printf "#DictSlotError<%d>:", $etp_dictdump_i
1263
set $etp_dictdump_flat = $etp_flat
1265
etp-1 ((Eterm)$etp_dictdump_p) 0
1266
set $etp_flat = $etp_dictdump_flat
1270
set $etp_dictdump_i++
1272
if $etp_dictdump_cnt != 0
1273
printf "#DictCntError<%d>, ", $etp_dictdump_cnt
1276
printf "%% Dictionary (0):\n["
1281
document etp-dictdump
1282
%---------------------------------------------------------------------------
1283
% etp-dictdump ErlProcDict*
1285
% Take an ErlProcDict* and print all entries in the process dictionary.
1286
%---------------------------------------------------------------------------
1289
define etpf-dictdump
1290
# Args: ErlProcDict*
1295
etp-dictdump ($arg0)
1299
document etpf-dictdump
1300
%---------------------------------------------------------------------------
1301
% etpf-dictdump ErlProcDict*
1303
% Same as etp-dictdump but print the values using etpf (flat).
1304
%---------------------------------------------------------------------------
1309
define etp-offheapdump
1310
# Args: ( ExternalThing* | ProcBin* | ErlFunThing* )
1314
set $etp_offheapdump_p = ($arg0)
1315
set $etp_offheapdump_i = 0
1316
set $etp_offheapdump_
1317
printf "%% Offheap dump:\n["
1318
while ($etp_offheapdump_p != 0) && ($etp_offheapdump_i < $etp_max_depth)
1319
if ((Eterm)$etp_offheapdump_p & 0x3) == 0x0
1320
if $etp_offheapdump_i > 0
1323
etp-1 ((Eterm)$etp_offheapdump_p|0x2) 0
1324
set $etp_offheapdump_p = $etp_offheapdump_p->next
1325
set $etp_offheapdump_i++
1327
printf "#TaggedPtr<%#x>", $etp_offheapdump_p
1328
set $etp_offheapdump_p = 0
1334
document etp-offheapdump
1335
%---------------------------------------------------------------------------
1336
% etp-offheapdump ( ExternalThing* | ProcBin* | ErlFunThing* )
1338
% Take an pointer to a linked list and print the terms in the list
1339
% up to the max depth.
1340
%---------------------------------------------------------------------------
1343
define etpf-offheapdump
1344
# Args: ( ExternalThing* | ProcBin* | ErlFunThing* )
1349
etp-offheapdump ($arg0)
1353
document etpf-offheapdump
1354
%---------------------------------------------------------------------------
1355
% etpf-offheapdump ( ExternalThing* | ProcBin* | ErlFunThing* )
1357
% Same as etp-offheapdump but print the values using etpf (flat).
1358
%---------------------------------------------------------------------------
1363
define etp-search-heaps
1368
printf "%% Search all (<%u) process heaps for ", erts_max_processes
1373
etp-search-heaps-1 ((Eterm*)((Eterm)($arg0)&~3))
1376
define etp-search-heaps-1
1381
set $etp_search_heaps_q = erts_max_processes / 10
1382
set $etp_search_heaps_r = erts_max_processes % 10
1383
set $etp_search_heaps_t = 10
1384
set $etp_search_heaps_m = $etp_search_heaps_q
1385
if $etp_search_heaps_r > 0
1386
set $etp_search_heaps_m++
1387
set $etp_search_heaps_r--
1389
set $etp_search_heaps_i = 0
1390
set $etp_search_heaps_found = 0
1391
while $etp_search_heaps_i < erts_max_processes
1392
if process_tab[$etp_search_heaps_i]
1393
if (process_tab[$etp_search_heaps_i]->heap <= ($arg0)) && \
1394
(($arg0) < process_tab[$etp_search_heaps_i]->hend)
1395
printf "process_tab[%d]->heap+%d\n", $etp_search_heaps_i, \
1396
($arg0)-process_tab[$etp_search_heaps_i]->heap
1398
if (process_tab[$etp_search_heaps_i]->old_heap <= ($arg0)) && \
1399
(($arg0) <= process_tab[$etp_search_heaps_i]->old_hend)
1400
printf "process_tab[%d]->old_heap+%d\n", $etp_search_heaps_i, \
1401
($arg0)-process_tab[$etp_search_heaps_i]->old_heap
1403
set $etp_search_heaps_cnt = 0
1404
set $etp_search_heaps_p = process_tab[$etp_search_heaps_i]->mbuf
1405
while $etp_search_heaps_p && ($etp_search_heaps_cnt < $etp_max_depth)
1406
set $etp_search_heaps_cnt++
1407
if (&($etp_search_heaps_p->mem) <= ($arg0)) && \
1408
(($arg0) < &($etp_search_heaps_p->mem)+$etp_search_heaps_p->size)
1409
printf "process_tab[%d]->mbuf(%d)+%d\n", \
1410
$etp_search_heaps_i, $etp_search_heaps_cnt, \
1411
($arg0)-&($etp_search_heaps_p->mem)
1413
set $etp_search_heaps_p = $etp_search_heaps_p->next
1415
if $etp_search_heaps_p
1416
printf "process_tab[%d] %% Too many HeapFragments\n", \
1420
set $etp_search_heaps_i++
1421
if $etp_search_heaps_i > $etp_search_heaps_m
1422
printf "%% %d%%...\n", $etp_search_heaps_t
1423
set $etp_search_heaps_t += 10
1424
set $etp_search_heaps_m += $etp_search_heaps_q
1425
if $etp_search_heaps_r > 0
1426
set $etp_search_heaps_m++
1427
set $etp_search_heaps_r--
1431
printf "%% 100%%.\n"
1434
document etp-search-heaps
1435
%---------------------------------------------------------------------------
1436
% etp-search-heaps Eterm
1438
% Search all process heaps in process_tab[], including the heap fragments
1439
% (process_tab[]->mbuf) for the specified Eterm.
1440
%---------------------------------------------------------------------------
1445
define etp-search-alloc
1450
printf "%% Search allocated memory blocks for "
1455
set $etp_search_alloc_n = sizeof(erts_allctrs) / sizeof(*erts_allctrs)
1456
set $etp_search_alloc_i = 0
1457
while $etp_search_alloc_i < $etp_search_alloc_n
1458
if erts_allctrs[$etp_search_alloc_i].alloc
1459
set $etp_search_alloc_f = (erts_allctrs+$etp_search_alloc_i)
1460
while ($etp_search_alloc_f->alloc == debug_alloc) || \
1461
($etp_search_alloc_f->alloc == stat_alloc) || \
1462
($etp_search_alloc_f->alloc == map_stat_alloc)
1463
set $etp_search_alloc_f = \
1464
(ErtsAllocatorFunctions_t*)$etp_search_alloc_f->extra
1466
if ($etp_search_alloc_f->alloc != erts_sys_alloc) && \
1467
($etp_search_alloc_f->alloc != erts_fix_alloc)
1468
if ($etp_search_alloc_f->alloc == erts_alcu_alloc) || \
1469
($etp_search_alloc_f->alloc == erts_alcu_alloc_ts)
1471
set $etp_search_alloc_e = (Allctr_t*)$etp_search_alloc_f->extra
1473
set $etp_search_alloc_p = $etp_search_alloc_e->mbc_list.first
1474
set $etp_search_alloc_cnt = 0
1475
while $etp_search_alloc_p && \
1476
($etp_search_alloc_cnt < $etp_max_depth)
1477
set $etp_search_alloc_cnt++
1478
if $etp_search_alloc_p <= ($arg0) && \
1479
($arg0) < (char*)$etp_search_alloc_p + \
1480
($etp_search_alloc_p->chdr & (Uint)~7)
1481
printf "erts_allctrs[%d] %% %salloc: mbc_list: %d\n", \
1482
$etp_search_alloc_i, $etp_search_alloc_e->name_prefix, \
1483
$etp_search_alloc_cnt
1485
if $etp_search_alloc_p == $etp_search_alloc_e->mbc_list.last
1486
if $etp_search_alloc_p->next
1488
"erts_allctrs[%d] %% %salloc: mbc_list.last error %p\n",\
1489
$etp_search_alloc_i, $etp_search_alloc_e->name_prefix,\
1492
set $etp_search_alloc_p = 0
1494
set $etp_search_alloc_p = $etp_search_alloc_p->next
1497
if $etp_search_alloc_p
1498
printf "erts_allctrs[%d] %% %salloc: too large mbc_list %p\n", \
1499
$ept_search_alloc_i, $etp_search_alloc_e->name_prefix,
1503
set $etp_search_alloc_p = $etp_search_alloc_e->sbc_list.first
1504
set $etp_search_alloc_cnt = 0
1505
while $etp_search_alloc_p && \
1506
($etp_search_alloc_cnt < $etp_max_depth)
1507
set $etp_search_alloc_cnt++
1508
if $etp_search_alloc_p <= ($arg0) && \
1509
($arg0) < (char*)$etp_search_alloc_p + \
1510
($etp_search_alloc_p->chdr & (Uint)~7)
1511
printf "erts_allctrs[%d] %% %salloc: sbc_list: %d\n", \
1512
$etp_search_alloc_i, $etp_search_alloc_e->name_prefix, \
1513
$etp_search_alloc_cnt
1515
if $etp_search_alloc_p == $etp_search_alloc_e->sbc_list.last
1516
if $etp_search_alloc_p->next
1518
"erts_allctrs[%d] %% %salloc: sbc_list.last error %p",\
1519
$etp_search_alloc_i, $etp_search_alloc_e->name_prefix,\
1522
set $etp_search_alloc_p = 0
1524
set $etp_search_alloc_p = $etp_search_alloc_p->next
1527
if $etp_search_alloc_p
1528
printf "erts_allctrs[%d] %% %salloc: too large sbc_list %p\n", \
1529
$ept_search_alloc_i, $etp_search_alloc_e->name_prefix,
1533
printf "erts_allctrs[%d] %% %s: unknown allocator\n", \
1534
$etp_search_alloc_i, erts_alc_a2ad[$etp_search_alloc_i]
1538
set $etp_search_alloc_i++
1542
document etp-search-alloc
1543
%---------------------------------------------------------------------------
1544
% etp-search-heaps Eterm
1546
% Search all internal allocator memory blocks for for the specified Eterm.
1547
%---------------------------------------------------------------------------
1552
define etp-overlapped-heaps
1557
printf "%% Dumping heap addresses to \"etp-commands.bin\"\n"
1558
set $etp_overlapped_heaps_q = erts_max_processes / 10
1559
set $etp_overlapped_heaps_r = erts_max_processes % 10
1560
set $etp_overlapped_heaps_t = 10
1561
set $etp_overlapped_heaps_m = $etp_overlapped_heaps_q
1562
if $etp_overlapped_heaps_r > 0
1563
set $etp_overlapped_heaps_m++
1564
set $etp_overlapped_heaps_r--
1566
set $etp_overlapped_heaps_i = 0
1567
set $etp_overlapped_heaps_found = 0
1568
dump binary value etp-commands.bin 'o'
1569
append binary value etp-commands.bin 'v'
1570
append binary value etp-commands.bin 'e'
1571
append binary value etp-commands.bin 'r'
1572
append binary value etp-commands.bin 'l'
1573
append binary value etp-commands.bin 'a'
1574
append binary value etp-commands.bin 'p'
1575
append binary value etp-commands.bin 'p'
1576
append binary value etp-commands.bin 'e'
1577
append binary value etp-commands.bin 'd'
1578
append binary value etp-commands.bin '-'
1579
append binary value etp-commands.bin 'h'
1580
append binary value etp-commands.bin 'e'
1581
append binary value etp-commands.bin 'a'
1582
append binary value etp-commands.bin 'p'
1583
append binary value etp-commands.bin 's'
1584
append binary value etp-commands.bin '\0'
1585
while $etp_overlapped_heaps_i < erts_max_processes
1586
if process_tab[$etp_overlapped_heaps_i]
1587
append binary value etp-commands.bin \
1588
(Eterm)$etp_overlapped_heaps_i
1589
append binary value etp-commands.bin \
1590
(Eterm)process_tab[$etp_overlapped_heaps_i]->heap
1591
append binary value etp-commands.bin \
1592
(Eterm)process_tab[$etp_overlapped_heaps_i]->hend
1593
append binary value etp-commands.bin \
1594
(Eterm)process_tab[$etp_overlapped_heaps_i]->old_heap
1595
append binary value etp-commands.bin \
1596
(Eterm)process_tab[$etp_overlapped_heaps_i]->old_hend
1597
set $etp_overlapped_heaps_p = process_tab[$etp_overlapped_heaps_i]->mbuf
1598
set $etp_overlapped_heaps_cnt = 0
1599
while $etp_overlapped_heaps_p && \
1600
($etp_overlapped_heaps_cnt < $etp_max_depth)
1601
set $etp_overlapped_heaps_cnt++
1602
append binary value etp-commands.bin \
1603
(Eterm)$etp_overlapped_heaps_p
1604
append binary value etp-commands.bin \
1605
(Eterm)(&($etp_overlapped_heaps_p->mem)+$etp_overlapped_heaps_p->size)
1606
set $etp_overlapped_heaps_p = $etp_overlapped_heaps_p->next
1608
if $etp_overlapped_heaps_p
1609
printf "process_tab[%d] %% Too many HeapFragments\n", \
1610
$etp_overlapped_heaps_i
1612
append binary value etp-commands.bin (Eterm)0x0
1613
append binary value etp-commands.bin (Eterm)0x0
1615
set $etp_overlapped_heaps_i++
1616
if $etp_overlapped_heaps_i > $etp_overlapped_heaps_m
1617
printf "%% %d%%...\n", $etp_overlapped_heaps_t
1618
set $etp_overlapped_heaps_t += 10
1619
set $etp_overlapped_heaps_m += $etp_overlapped_heaps_q
1620
if $etp_overlapped_heaps_r > 0
1621
set $etp_overlapped_heaps_m++
1622
set $etp_overlapped_heaps_r--
1629
document etp-overlapped-heaps
1630
%---------------------------------------------------------------------------
1631
% etp-overlapped-heaps
1633
% Dump all process heap addresses in process_tab[], including
1634
% the heap fragments in binary format on the file etp-commands.bin.
1635
% Then call etp_commands:file/1 to analyze if any heaps overlap.
1637
% Requires 'erl' in the path and 'etp_commands.beam' in 'erl's search path.
1638
%---------------------------------------------------------------------------
1647
etp-chart-start ($arg0)
1648
set ($arg0) = ($arg0)
1649
etp-msgq (($arg0)->msg)
1650
etp-stackdump ($arg0)
1651
etp-dictdump (($arg0)->dictionary)
1652
etp-dictdump (($arg0)->debug_dictionary)
1653
printf "%% Dumping other process data...\n"
1654
etp ($arg0)->seq_trace_token
1656
printf "%% Dumping done.\n"
1661
%---------------------------------------------------------------------------
1662
% etp-chart Process*
1664
% Dump all process data to the file "etp-commands.bin" and then use
1665
% the Erlang support module to print a memory chart of all terms.
1666
%---------------------------------------------------------------------------
1671
define etp-chart-start
1676
set $etp_chart_id = 0
1677
set $etp_chart_start_p = ($arg0)
1678
dump binary value etp-commands.bin 'c'
1679
append binary value etp-commands.bin 'h'
1680
append binary value etp-commands.bin 'a'
1681
append binary value etp-commands.bin 'r'
1682
append binary value etp-commands.bin 't'
1683
append binary value etp-commands.bin '\0'
1684
append binary value etp-commands.bin (Eterm)($etp_chart_start_p->heap)
1685
append binary value etp-commands.bin (Eterm)($etp_chart_start_p->high_water)
1686
append binary value etp-commands.bin (Eterm)($etp_chart_start_p->hend)
1687
append binary value etp-commands.bin (Eterm)($etp_chart_start_p->old_heap)
1688
append binary value etp-commands.bin (Eterm)($etp_chart_start_p->old_hend)
1689
set $etp_chart_start_cnt = 0
1690
set $etp_chart_start_p = $etp_chart_start_p->mbuf
1691
while $etp_chart_start_p && ($etp_chart_start_cnt < $etp_max_depth)
1692
set $etp_chart_start_cnt++
1693
append binary value etp-commands.bin (Eterm)($etp_chart_start_p->mem)
1694
append binary value etp-commands.bin (Eterm)($etp_chart_start_p->size)
1695
set $etp_chart_start_p = $etp_chart_start_p->next
1697
append binary value etp-commands.bin (Eterm)(0)
1698
append binary value etp-commands.bin (Eterm)(0)
1699
if $etp_chart_start_p
1700
printf "%% Too many HeapFragments\n"
1704
document etp-chart-start
1705
%---------------------------------------------------------------------------
1706
% etp-chart-start Process*
1708
% Dump a chart head to the file "etp-commands.bin".
1709
%---------------------------------------------------------------------------
1714
define etp-chart-entry-1
1715
# Args: Eterm, int depth, int words
1720
printf "#%d:", $etp_chart_id
1722
append binary value etp-commands.bin ($arg0)&~0x3
1723
append binary value etp-commands.bin (Eterm)(($arg2)*sizeof(Eterm))
1724
append binary value etp-commands.bin (Eterm)$etp_chart_id
1725
append binary value etp-commands.bin (Eterm)($arg1)
1726
# printf "<dumped %#x %lu %lu %lu>", ($arg0)&~0x3, \
1727
# (Eterm)(($arg2)*sizeof(Eterm)), (Eterm)$etp_chart_id, (Eterm)($arg1)
1732
define etp-chart-print
1737
document etp-chart-print
1738
%---------------------------------------------------------------------------
1739
% etp-chart-print Process*
1741
% Print a memory chart of the dumped data in "etp-commands.bin", and stop
1743
%---------------------------------------------------------------------------
1746
############################################################################
1750
define etp-ets-tables
1754
printf "%% Dumping < %lu ETS tables\n", (unsigned long)db_max_tabs
1755
while $etp_ets_tables_i < db_max_tabs
1756
if (db_tables[$etp_ets_tables_i].id != 0x18) && \
1757
(db_tables[$etp_ets_tables_i].id != 0xd8)
1758
printf "%% %d:", $etp_ets_tables_i
1759
etp-1 ((Eterm)(db_tables[$etp_ets_tables_i].id)) 0
1761
etp-1 ((Eterm)(db_tables[$etp_ets_tables_i].t->common.owner)) 0
1764
set $etp_ets_tables_i++
1766
set $etp_ets_table_i = 0
1769
document etp-ets-tables
1770
%---------------------------------------------------------------------------
1773
% Dump all ETS table names and their indexies.
1774
%---------------------------------------------------------------------------
1777
define etp-ets-tabledump
1778
# Args: int tableindex
1781
printf "%% Dumping ETS table %d:", ($arg0)
1782
set $etp_ets_tabledump_n = 0
1783
set $etp_ets_tabledump_t = db_tables[($arg0)].t
1784
set $etp_ets_tabledump_i = 0
1785
etp-1 ($etp_ets_tabledump_t->common.the_name) 0
1786
printf " status=%#x\n", $etp_ets_tabledump_t->common.status
1787
if $etp_ets_tabledump_t->common.status & 0x130
1789
set $etp_ets_tabledump_h = $etp_ets_tabledump_t->hash
1790
printf "%% nitems=%d\n", $etp_ets_tabledump_h->nitems
1791
while $etp_ets_tabledump_i < $etp_ets_tabledump_h->nactive
1792
set $etp_ets_tabledump_l = $etp_ets_tabledump_h->seg \
1793
[$etp_ets_tabledump_i>>8][$etp_ets_tabledump_i&0xFF]
1794
if $etp_ets_tabledump_l
1795
printf "%% Slot %d:\n", $etp_ets_tabledump_i
1796
while $etp_ets_tabledump_l
1797
if $etp_ets_tabledump_n
1802
set $etp_ets_tabledump_n++
1803
etp-1 ((Eterm)($etp_ets_tabledump_l->dbterm.tpl)|0x2) 0
1804
if $etp_ets_tabledump_l->hvalue == ((unsigned long)-1)
1809
set $etp_ets_tabledump_l = $etp_ets_tabledump_l->next
1810
if $etp_ets_tabledump_n >= $etp_max_depth
1811
set $etp_ets_tabledump_l = 0
1815
set $etp_ets_tabledump_i++
1817
if $etp_ets_tabledump_n
1821
printf "%% Not a hash table\n"
1825
document etp-ets-tabledump
1826
%---------------------------------------------------------------------------
1827
% etp-ets-tabledump Slot
1829
% Dump an ETS table with a specified slot index.
1830
%---------------------------------------------------------------------------
1833
############################################################################
1834
# Erlang support module handling
1838
shell make -f "${ROOTDIR:?}/erts/etc/unix/etp_commands.mk" \
1839
ROOTDIR="${ROOTDIR:?}" ETP_DATA="etp-commands.bin"
1843
%---------------------------------------------------------------------------
1846
% Make and run the Erlang support module on the input file
1847
% "erl-commands.bin". The environment variable ROOTDIR must
1848
% be set to find $ROOTDIR/erts/etc/unix/etp_commands.mk.
1850
% Also, erl and erlc must be in the path.
1851
%---------------------------------------------------------------------------
1854
############################################################################
1855
# Toolbox parameter handling
1858
define etp-set-max-depth
1860
set $etp_max_depth = ($arg0)
1862
echo %%%Error: max-depth <= 0 %%%\n
1866
document etp-set-max-depth
1867
%---------------------------------------------------------------------------
1868
% etp-set-max-depth Depth
1870
% Set the max term depth to use for etp. The term dept limit
1871
% works in both depth and width, so if you set the max depth to 10,
1872
% an 11 element flat tuple will be truncated.
1873
%---------------------------------------------------------------------------
1876
define etp-set-max-string-length
1878
set $etp_max_string_length = ($arg0)
1880
echo %%%Error: max-string-length <= 0 %%%\n
1884
document etp-set-max-string-length
1885
%---------------------------------------------------------------------------
1886
% etp-set-max-strint-length Length
1888
% Set the max string length to use for ept when printing lists
1889
% that can be shown as printable strings. Printable strings
1890
% that are longer will be truncated, and not even checked if
1891
% they really are printable all the way to the end.
1892
%---------------------------------------------------------------------------
1896
printf "etp-set-max-depth %d\n", $etp_max_depth
1897
printf "etp-set-max-string-length %d\n", $etp_max_string_length
1901
%---------------------------------------------------------------------------
1904
% Show the commands needed to set all etp parameters
1905
% to their current value.
1906
%---------------------------------------------------------------------------
1909
############################################################################
1915
set $etp_nil = 0xfffffffb
1916
set $etp_chart_id = 0
1919
set $etp_max_depth = 20
1920
set $etp_max_string_length = 100
1922
set $etp_ets_tables_i = 0
1926
%---------------------------------------------------------------------------
1927
% Use etp-help for a command overview and general help.
1929
% To use the Erlang support module, the environment variable ROOTDIR
1930
% must be set to the toplevel installation directory of Erlang/OTP,
1931
% so the etp-commands file becomes:
1932
% $ROOTDIR/erts/etc/unix/etp-commands
1933
% Also, erl and erlc must be in the path.
1934
%---------------------------------------------------------------------------