aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2017-11-21 09:16:56 +0100
committerBjörn Gustavsson <[email protected]>2017-11-21 12:39:59 +0100
commit892dd54fa032de737defbee22534117b1c261c60 (patch)
tree14866de218b0e2a757f66c10691448d1084f8023
parent533ea3ef982965a8e75305f6cd5b89e8fb046d35 (diff)
downloadotp-892dd54fa032de737defbee22534117b1c261c60.tar.gz
otp-892dd54fa032de737defbee22534117b1c261c60.tar.bz2
otp-892dd54fa032de737defbee22534117b1c261c60.zip
Correct parsing of sub binaries
Correct several problems parsing sub binaries. A sub binary would often be replaced with '#CDVNonexistingBinary'. When parsing a sub binary, we must scan ahead to find the definition of the refc or heap binary being referenced.
-rw-r--r--lib/observer/src/crashdump_viewer.erl74
-rw-r--r--lib/observer/test/crashdump_helper.erl14
-rw-r--r--lib/observer/test/crashdump_viewer_SUITE.erl8
3 files changed, 70 insertions, 26 deletions
diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl
index be9204f729..3aeca78e10 100644
--- a/lib/observer/src/crashdump_viewer.erl
+++ b/lib/observer/src/crashdump_viewer.erl
@@ -2660,27 +2660,25 @@ parse_heap_term("Yc"++Line0, Addr, DecodeOpts, D0) -> %Reference-counted binary.
{Offset,":"++Line2} = get_hex(Line1),
{Sz,Line} = get_hex(Line2),
Binp = Binp0 bor DecodeOpts#dec_opts.bin_addr_adj,
- Term = case lookup_binary_index(Binp) of
- [{_,Start}] -> cdvbin(Offset,Sz,{'#CDVBin',Start});
- [] -> '#CDVNonexistingBinary'
- end,
- D = gb_trees:insert(Addr, Term, D0),
- {Term,Line,D};
+ case lookup_binary_index(Binp) of
+ [{_,Start}] ->
+ SymbolicBin = {'#CDVBin',Start},
+ Term = cdvbin(Offset, Sz, SymbolicBin),
+ D1 = gb_trees:insert(Addr, Term, D0),
+ D = gb_trees:insert(Binp, SymbolicBin, D1),
+ {Term,Line,D};
+ [] ->
+ Term = '#CDVNonexistingBinary',
+ D1 = gb_trees:insert(Addr, Term, D0),
+ D = gb_trees:insert(Binp, Term, D1),
+ {Term,Line,D}
+ end;
parse_heap_term("Ys"++Line0, Addr, DecodeOpts, D0) -> %Sub binary.
{Binp0,":"++Line1} = get_hex(Line0),
{Offset,":"++Line2} = get_hex(Line1),
- {Sz,Line} = get_hex(Line2),
- Binp = Binp0 bor DecodeOpts#dec_opts.bin_addr_adj,
- Term = case lookup_binary_index(Binp) of
- [{_,Start}] -> cdvbin(Offset,Sz,{'#CDVBin',Start});
- [] ->
- %% Might it be on the heap?
- case gb_trees:lookup(Binp, D0) of
- {value,Bin} -> cdvbin(Offset,Sz,Bin);
- none -> '#CDVNonexistingBinary'
- end
- end,
- D = gb_trees:insert(Addr, Term, D0),
+ {Sz,Line3} = get_hex(Line2),
+ {Term,Line,D1} = deref_bin(Binp0, Offset, Sz, Line3, DecodeOpts, D0),
+ D = gb_trees:insert(Addr, Term, D1),
{Term,Line,D};
parse_heap_term("Mf"++Line0, Addr, DecodeOpts, D0) -> %Flatmap.
{Size,":"++Line1} = get_hex(Line0),
@@ -2789,11 +2787,39 @@ parse_atom_translation_table(0, Line0, As) ->
parse_atom_translation_table(N, Line0, As) ->
{A, Line1, _} = parse_atom(Line0, []),
parse_atom_translation_table(N-1, Line1, [A|As]).
-
-
-deref_ptr(Ptr, Line, DecodeOpts, D0) ->
- case gb_trees:lookup(Ptr, D0) of
+
+deref_ptr(Ptr, Line, DecodeOpts, D) ->
+ Lookup = fun(D0) ->
+ gb_trees:lookup(Ptr, D0)
+ end,
+ do_deref_ptr(Lookup, Line, DecodeOpts, D).
+
+deref_bin(Binp0, Offset, Sz, Line, DecodeOpts, D) ->
+ Binp = Binp0 bor DecodeOpts#dec_opts.bin_addr_adj,
+ Lookup = fun(D0) ->
+ lookup_binary(Binp, Offset, Sz, D0)
+ end,
+ do_deref_ptr(Lookup, Line, DecodeOpts, D).
+
+lookup_binary(Binp, Offset, Sz, D) ->
+ case lookup_binary_index(Binp) of
+ [{_,Start}] ->
+ Term = cdvbin(Offset, Sz, {'#CDVBin',Start}),
+ {value,Term};
+ [] ->
+ case gb_trees:lookup(Binp, D) of
+ {value,<<_:Offset/bytes,Sub:Sz/bytes,_/bytes>>} ->
+ {value,Sub};
+ {value,SymbolicBin} ->
+ {value,cdvbin(Offset, Sz, SymbolicBin)};
+ none ->
+ none
+ end
+ end.
+
+do_deref_ptr(Lookup, Line, DecodeOpts, D0) ->
+ case Lookup(D0) of
{value,Term} ->
{Term,Line,D0};
none ->
@@ -2805,11 +2831,11 @@ deref_ptr(Ptr, Line, DecodeOpts, D0) ->
case bytes(Fd) of
"="++_ ->
put(fd, end_of_heap),
- deref_ptr(Ptr, Line, DecodeOpts, D0);
+ do_deref_ptr(Lookup, Line, DecodeOpts, D0);
L ->
update_progress(length(L)+1),
D = parse(L, DecodeOpts, D0),
- deref_ptr(Ptr, Line, DecodeOpts, D)
+ do_deref_ptr(Lookup, Line, DecodeOpts, D)
end
end
end.
diff --git a/lib/observer/test/crashdump_helper.erl b/lib/observer/test/crashdump_helper.erl
index 41041682c2..bb1755f530 100644
--- a/lib/observer/test/crashdump_helper.erl
+++ b/lib/observer/test/crashdump_helper.erl
@@ -21,7 +21,7 @@
-module(crashdump_helper).
-export([n1_proc/2,remote_proc/2,
dump_maps/0,create_maps/0,
- create_binaries/0]).
+ create_binaries/0,create_sub_binaries/1]).
-compile(r18).
-include_lib("common_test/include/ct.hrl").
@@ -64,6 +64,7 @@ n1_proc(Creator,_N2,Pid2,Port2,_L) ->
put(bin,Bin),
put(bins,create_binaries()),
put(sub_bin,SubBin),
+ put(sub_bins,create_sub_binaries(get(bins))),
put(bignum,83974938738373873),
put(neg_bignum,-38748762783736367),
put(ext_pid,Pid2),
@@ -104,6 +105,17 @@ create_binaries() ->
<<Data:Size/unit:8>>
end || Size <- Sizes].
+create_sub_binaries(Bins) ->
+ [create_sub_binary(Bin, Start, LenSub) ||
+ Bin <- Bins,
+ Start <- [0,1,2,3,4,5,10,22],
+ LenSub <- [0,1,2,3,4,6,9]].
+
+create_sub_binary(Bin, Start, LenSub) ->
+ Len = byte_size(Bin) - LenSub - Start,
+ <<_:Start/bytes,Sub:Len/bytes,_/bytes>> = Bin,
+ Sub.
+
%%%
%%% Test dumping of maps. Dumping of maps only from OTP 20.2.
%%%
diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl
index 29b9e406ae..b2777aed46 100644
--- a/lib/observer/test/crashdump_viewer_SUITE.erl
+++ b/lib/observer/test/crashdump_viewer_SUITE.erl
@@ -403,6 +403,10 @@ special(File,Procs) ->
verify_binaries(Binaries, proplists:get_value(bins,Dict)),
io:format(" binaries ok",[]),
+ SubBinaries = crashdump_helper:create_sub_binaries(Binaries),
+ verify_binaries(SubBinaries, proplists:get_value(sub_bins,Dict)),
+ io:format(" sub binaries ok",[]),
+
#proc{last_calls=LastCalls} = ProcDetails,
true = length(LastCalls) =< 4,
@@ -461,7 +465,9 @@ special(File,Procs) ->
%% i.e. no binary exist in the dump
[#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs),
Pid = pid_to_list(Pid0),
- {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid),
+ %%WarnIncompleteHeap = ["WARNING: This process has an incomplete heap. Some information might be missing."],
+ {ok,ProcDetails=#proc{},[]} =
+ crashdump_viewer:proc_details(Pid),
io:format(" process details ok",[]),
#proc{dict=Dict} = ProcDetails,