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 + -
显示快捷键?