crashdump_translate.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,132 行 · 第 1/3 页

ERL
1,132
字号
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %%     $Id$%%-module(crashdump_translate).%% %% This module translates an old erlang crash dump (pre OTP R10) to%% the new format with tags that can be read by the crashdump viewer%% tool.%%%% API%-compile(export_all).-export([old2new/2]).-define(divider,"--------------------------------------------------\n").-define(chunk_size,1000). % number of bytes read from crashdump at a time-define(max_line_size,500). % max number of bytes (i.e. characters) the			    % line/1 function can return-define(backwards_chunk_size,10000). % number of bytes read from crashdump                                      % at a time when reading atoms%%%-----------------------------------------------------------------%%% Translate an old dump to a newer formatold2new(ReadFile,WriteFile) ->    case {file:open(ReadFile,[read,read_ahead,raw,binary]),	  file:open(WriteFile,[write,delayed_write,raw,binary])} of	{{ok,Read},{ok,Write}} -> 	    case catch translate(Read,Write) of		{'EXIT',_Reason} = EXIT -> 		    exit(EXIT);		_other -> % thown if dump is truncated		    erase(chunk),		    file:close(Read),		    file:close(Write)	    end;	{{ok,Read},Error} -> 	    file:close(Read),	    {error,{open,WriteFile,Error}};	{Error,{ok,Write}} -> 	    file:close(Write),	    {error,{open,ReadFile,Error}};	{ReadError,WriteError} -> 	    {error,{open,{ReadFile,ReadError},{WriteFile,WriteError}}}    end.%%%-----------------------------------------------------------------%%% Internal functionstranslate(Read,Write) ->    {Truncated,InputLine} = 	case line(Read) of	    {eof,InputLine0} -> {true,InputLine0};	    InputLine0 -> {false,InputLine0}	end,    case InputLine of	"<Erlang crash dump>\n" ->	    write(Write,"=erl_crash_dump:0.0\n"),	    translate_summary(Read,Write),	    translate(Read,Write);	"\n" ->	    translate(Read,Write);	?divider ->	    translate(Read,Write);	"Process Information\n" ->	    drop_line(Read), % divider	    translate_processes(Read,Write),	    translate(Read,Write);	"Zombie Process Information\n" ->	    %% throwing away zombie information	    _ = line(Read), % "Processes kept: ...."	    _ = line(Read), % probably a divider	    translate(Read,Write);	"Port Information\n" ->	    drop_line(Read), % divider	    translate_ports(Read,Write),	    translate(Read,Write);	"Internal Table Information\n" ->	    drop_line(Read), % divider	    translate_internal_tables(Read,Write),	    translate(Read,Write);	"ETS tables\n" ->	    drop_line(Read), % divider	    translate_ets_tables(Read,Write),	    translate(Read,Write);	"Timers\n" ->	    drop_line(Read), % divider	    translate_timers(Read,Write),	    translate(Read,Write);	"Distribution Information\n" ->	    translate_dist_info(Read,Write),	    translate(Read,Write);	"Loaded Modules Information\n" ->	    drop_line(Read), % divider	    translate_loaded_modules(Read,Write),	    translate(Read,Write);	"Fun table\n" ->	    drop_line(Read), % divider	    translate_funs(Read,Write),	    translate(Read,Write);	"Atoms\n" ->	    drop_line(Read), % divider	    write(Write,"=atoms\n"),	    translate_atoms(Read,Write),%	    {_,{Atoms,N}} = read_to_empty_line_reverse(Read),%	    write(Write,[Atoms,"=num_atoms:",integer_to_list(N),"\n"]),	    translate(Read,Write);	"Memory allocation information\n" -> 	    write(Write,"=old_instr_data\n"),	    drop_to_empty_line(Read),	    translate(Read,Write);	"<End of Erlang crash dump>\n" ->	    write(Write,"=end\n");	PartOfLine when Truncated ->	    truncated(PartOfLine);	Line ->	    unexpected(Line),	    translate(Read,Write)    end.translate_summary(Read,Write) ->    copy_line(Read,Write), % date    drop_line(Read), % newline    copy_line(Read,Write), % slogan    drop_line(Read), % newline    drop_line(Read), % newline    system_version(Read,Write), % emulator    copy_line(Read,Write,"Compiled: "). % compile time    system_version(Read,Write) ->    Heading = "System version: ",    {Truncated,InputLine} = 	case line(Read) of	    {eof,InputLine0} -> {true,InputLine0};	    InputLine0 -> {false,InputLine0}	end,    case InputLine of	"Erlang (BEAM) emulator version " ++ Rest ->	    {ErtsVsn,_} = split(Rest),	    put(erts_vsn,ErtsVsn),	    write(Write,[Heading,InputLine]);	_ ->	    write(Write,[Heading,InputLine])    end,    if Truncated -> truncated();       true -> ok    end.translate_processes(Read,Write) ->    {Truncated,InputLine} = 	case line(Read) of	    {eof,InputLine0} -> {true,InputLine0};	    InputLine0 -> {false,InputLine0}	end,    case InputLine of	"\n" ->	    ok;  % all processes translated	Line -> 	    %% handles both Line and {eof,PartOfLine}	    Rest1 = copy_word(Write,Line,$ ,"=proc:"), 	    ModifiedRest1 = 		case Rest1 of		    "Process is garbing, limited information." ++ R2 ->			"Garbing." ++ R2;		    _ ->			Rest1		end,	    Rest2 = copy_word(Write,ModifiedRest1,$.,"State: "),	    case Rest2 of		"\n" -> 		    ok;		" Registered as: " ++ NameNl ->		    write(Write,["Name: ",NameNl]);		    		TruncText when Truncated ->		    truncated(TruncText);	        Unexpected ->		    unexpected(Unexpected)	    end,	    translate_process(Read,Write,line(Read))    end.translate_process(Read,Write,InputLine0) ->    {Truncated,InputLine} = 	case InputLine0 of	    {eof,I} -> {true,I};	    InputLine0 -> {false,InputLine0}	end,    case InputLine of	?divider ->	    translate_processes(Read,Write); % translate next process	"Spawned as: " ++ _Func = InitFuncNl ->	    write(Write,InitFuncNl),	    translate_process(Read,Write,line(Read));	"Message buffer data: " ++ Rest ->	    write(Write,["Heap fragment data: ", Rest]),	    translate_process(Read,Write,line(Read));	"Message queue (" ++ Rest ->	    write_msg_q_stuff(Write,Rest,Truncated),	    translate_process(Read,Write,line(Read));	{part,"Message queue (" ++ Rest} ->	    write_msg_q_stuff(Write,Rest,Truncated),	    write_rest_of_line(Read,Write),	    translate_process(Read,Write,line(Read));	"Last calls:" ++ _nl ->	    write(Write,"Last calls: "),	    NextLine = write_last_calls(Read,Write),	    translate_process(Read,Write,NextLine);	"Reductions " ++ Rest1 ->	    Rest2 = copy_word(Write,Rest1,$ ,"Reductions: "),	    case Rest2 of		"stack+heap " ++ Rest3 ->		    Rest4 = copy_word(Write,Rest3,$ ,"Stack+heap: "),		    case Rest4 of			"old_heap_sz=" ++ OldHeapNl ->			    write(Write,["OldHeap: ",OldHeapNl]);			TruncText when Truncated ->			    truncated(TruncText);			Unexpected ->			    unexpected(Unexpected)		    end;		"heap_sz " ++ _Rest3 ->		    write(Write,"Stack: -1\n"),		    put(shared_heap,true);		TruncText when Truncated ->		    truncated(TruncText);		Unexpected ->		    unexpected(Unexpected)	    end,	    translate_process(Read,Write,line(Read));	"Heap unused=" ++ Rest1 ->	    case get(shared_heap) of		true ->		    ok;		_ ->		    Rest2 = copy_word(Write,Rest1,$ ,"Heap unused: "),		    case Rest2 of			"OldHeap unused=" ++ OldHeapUnusedNl ->			    write(Write,["OldHeap unused: ",OldHeapUnusedNl]);			TruncText when Truncated ->			    truncated(TruncText);			Unexpected ->			    unexpected(Unexpected)		    end	    end,	    translate_process(Read,Write,line(Read));	"new heap: start    top      sp       end" ++ _ ->	    NewHeapLine = case line(Read) of			      {eof,L} -> {eof,string:strip(L,left)};			      L -> string:strip(L,left)			  end,	    New1 = copy_word(Write,NewHeapLine,$ ,"New heap start: "),	    New2 = copy_word(Write,New1,$ ,"New heap top: "),	    New3 = copy_word(Write,New2,$ ,"Stack top: "),	    _New4 = copy_word(Write,New3,$ ,"Stack end: "),	    translate_process(Read,Write,line(Read));	"old heap: start    top      end" ++ _ ->	    OldHeapLine = case line(Read) of			      {eof,L} -> {eof,string:strip(L,left)};			      L -> string:strip(L,left)			  end,	    Old1 = copy_word(Write,OldHeapLine,$ ,"Old heap start: "),	    Old2 = copy_word(Write,Old1,$ ,"Old heap top: "),	    _Old3 = copy_word(Write,Old2,$ ,"Old heap end: "),	    translate_process(Read,Write,line(Read));	{part,Line} ->	    write(Write,Line),	    write_rest_of_line(Read,Write),	    translate_process(Read,Write,line(Read));	PartOfLine when Truncated ->	    truncated(PartOfLine);	Line ->	    write(Write,Line),	    translate_process(Read,Write,line(Read))    end.write_msg_q_stuff(Write,Rest1,Truncated) ->    Rest2 = copy_word(Write,Rest1,$ ,"Message queue length: "),    case Rest2 of	"messages): " ++ MsgQ ->	    write(Write,["Message queue: ",MsgQ]);	"message): " ++ MsgQ ->	    write(Write,["Message queue: ",MsgQ]);	TruncText when Truncated ->	    truncated(TruncText);	Unexpected ->	    unexpected(Unexpected)    end.write_last_calls(Read,Write) ->    case line(Read) of	"  " ++ Call -> 	    write(Write,[Call--"\n"," "]),	    write_last_calls(Read,Write);	Line -> 	    write(Write,"\n"),	    Line    end.translate_ports(Read,Write) ->    case line(Read) of	"\n" ->	    ok;	?divider ->	    translate_ports(Read,Write);	"<" ++ Rest ->	    {Slot,_nl} = split($>,Rest),	    write(Write,["=port:#Port<0.",Rest,"Slot: ",Slot,"\n"]),	    translate_ports(Read,Write);	"Port is UNIX fd " ++ Rest0 ->	    {Fd,Rest1} = split(Rest0),	    write(Write,["Port is UNIX fd ",Rest1--"\n",": ",Fd,"\n"]),	    translate_ports(Read,Write);	{eof,PartOfLine} ->	    truncated(PartOfLine);	Line ->	    write(Write,Line),	    translate_ports(Read,Write)    end.translate_internal_tables(Read,Write) ->    translate_internal_tables(Read,Write,[]).translate_internal_tables(Read,Write,AtomSpace) ->    Line = line(Read),    {Truncated,InputLine} = 	case Line of	    {eof,InputLine0} -> {true,InputLine0};	    InputLine0 -> {false,InputLine0}	end,    case InputLine of	"Hash Table(" ++ Rest ->	    translate_hash_table(Write,Rest),	    translate_internal_tables(Read,Write,AtomSpace);	"Index Table(" ++ Rest ->	    translate_index_table(Write,Rest),	    translate_internal_tables(Read,Write,AtomSpace);	"Atom space  " ++ Rest ->	    {Used,Allocated} = split($/,Rest),	    translate_internal_tables(Read,Write,{Used,Allocated--"\n"});	"Allocated " ++ _ ->	    translate_allocated_areas(Read,Write,Line,AtomSpace);	"sl_alloc: disabled\n" ->	    write(Write,"=allocator:sl_alloc\noption e: false\n"),	    translate_internal_tables(Read,Write,AtomSpace);	"sl_alloc: ver(" ++ Rest ->	    translate_sl_alloc(Read,Write,Rest,AtomSpace);	"sl_alloc: carriers size(" ++ Rest ->	    translate_sl_alloc_r7_r8(Write,"carriers size",Rest),	    translate_internal_tables(Read,Write,AtomSpace);	"Mmap chunks " ++ Chunks ->	    write(Write,["=allocator:sl_alloc\nversion: release1\nmmap chunks: ",			 Chunks]),	    case line(Read) of		"Mmap size " ++ Size ->		    write(Write,["mmap size: ",Size]);		{eof,PartOfLine} ->		    truncated(PartOfLine)	    end,	    translate_internal_tables(Read,Write,AtomSpace);	"Memory (bytes):\n" ->	    write(Write,"=memory\n"),	    translate_memory_and_allocated_area_r9b(Read,Write,AtomSpace);	PartOfLine when Truncated ->	    truncated(PartOfLine);	Unexpected ->	    unexpected(Unexpected),

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?