1: %%
    2: %% %CopyrightBegin%
    3: %% 
    4: %% Copyright Ericsson AB 2000-2013. All Rights Reserved.
    5: %% 
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %% 
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %% 
   17: %% %CopyrightEnd%
   18: %%
   19: 
   20: -module(trace_local_SUITE).
   21: -compile({nowarn_deprecated_function, {erlang,hash,2}}).
   22: 
   23: -export([basic_test/0, bit_syntax_test/0, return_test/0,
   24: 	 on_and_off_test/0, stack_grow_test/0,
   25: 	 info_test/0, delete_test/1, exception_test/1,
   26: 	 not_run/1]).
   27: 
   28: -export([exported/1, exported_wrap/1, loop/4, apply_slave_async/5,
   29: 	 match/2, clause/2, id/1, undef/1, lists_reverse/2]).
   30: 
   31: %%
   32: %% Define to run outside of test server
   33: %%
   34: %% (rotten feature)
   35: %%
   36: %%-define(STANDALONE,1).
   37:  
   38: %%
   39: %% Define for debug output
   40: %%
   41: %%-define(debug,1).
   42:  
   43: -ifdef(STANDALONE).
   44: -define(config(A,B),config(A,B)).
   45: -export([config/2]).
   46: -define(DEFAULT_RECEIVE_TIMEOUT, 1000).
   47: -else.
   48: -include_lib("test_server/include/test_server.hrl").
   49: -define(DEFAULT_RECEIVE_TIMEOUT, infinity).
   50: -endif.
   51:  
   52: -ifdef(debug).
   53: -ifdef(STANDALONE).
   54: -define(line, erlang:display({?MODULE,?LINE}), ).
   55: -endif.
   56: -define(dbgformat(A,B),io:format(A,B)).
   57: -else.
   58: -ifdef(STANDALONE).
   59: -define(line, noop, ).
   60: -endif.
   61: -define(dbgformat(A,B),noop).
   62: -endif.
   63:  
   64: -ifdef(STANDALONE).
   65: config(priv_dir,_) ->
   66:     ".".
   67: -else.
   68: 
   69: %%% When run in test server %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   70: 
   71: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   72: 	 init_per_group/2,end_per_group/2, basic/1, bit_syntax/1,
   73: 	 return/1, on_and_off/1, systematic_on_off/1,
   74: 	 stack_grow/1,info/1, delete/1,
   75: 	 exception/1, exception_apply/1,
   76: 	 exception_function/1, exception_apply_function/1,
   77: 	 exception_nocatch/1, exception_nocatch_apply/1,
   78: 	 exception_nocatch_function/1, exception_nocatch_apply_function/1,
   79: 	 exception_meta/1, exception_meta_apply/1,
   80: 	 exception_meta_function/1, exception_meta_apply_function/1,
   81: 	 exception_meta_nocatch/1, exception_meta_nocatch_apply/1,
   82: 	 exception_meta_nocatch_function/1,
   83: 	 exception_meta_nocatch_apply_function/1,
   84: 	 concurrency/1,
   85: 	 init_per_testcase/2, end_per_testcase/2]).
   86: init_per_testcase(_Case, Config) ->
   87:     ?line Dog=test_server:timetrap(test_server:minutes(2)),
   88:     [{watchdog, Dog}|Config].
   89: 
   90: end_per_testcase(_Case, Config) ->
   91:     shutdown(),
   92:     Dog=?config(watchdog, Config),
   93:     test_server:timetrap_cancel(Dog),
   94: 
   95:     %% Reloading the module will clear all trace patterns, and
   96:     %% in a debug-compiled emulator run assertions of the counters
   97:     %% for the number of functions with breakpoints.
   98: 
   99:     c:l(?MODULE).
  100: 
  101: 
  102: 
  103: suite() -> [{ct_hooks,[ts_install_cth]}].
  104: 
  105: all() -> 
  106:     case test_server:is_native(trace_local_SUITE) of
  107: 	true -> [not_run];
  108: 	false ->
  109: 	    [basic, bit_syntax, return, on_and_off, systematic_on_off,
  110: 	     stack_grow,
  111: 	     info, delete, exception, exception_apply,
  112: 	     exception_function, exception_apply_function,
  113: 	     exception_nocatch, exception_nocatch_apply,
  114: 	     exception_nocatch_function,
  115: 	     exception_nocatch_apply_function, exception_meta,
  116: 	     exception_meta_apply, exception_meta_function,
  117: 	     exception_meta_apply_function, exception_meta_nocatch,
  118: 	     exception_meta_nocatch_apply,
  119: 	     exception_meta_nocatch_function,
  120: 	     exception_meta_nocatch_apply_function,
  121: 	     concurrency]
  122:     end.
  123: 
  124: groups() -> 
  125:     [].
  126: 
  127: init_per_suite(Config) ->
  128:     Config.
  129: 
  130: end_per_suite(_Config) ->
  131:     ok.
  132: 
  133: init_per_group(_GroupName, Config) ->
  134:     Config.
  135: 
  136: end_per_group(_GroupName, Config) ->
  137:     Config.
  138: 
  139: 
  140: not_run(Config) when is_list(Config) -> 
  141:     {skipped,"Native code"}.
  142: 
  143: basic(doc) ->
  144:     ["Tests basic local call-trace"];
  145: basic(Config) when is_list(Config) ->
  146:     basic_test().
  147: 
  148: bit_syntax(doc) ->
  149:     "OTP-7399: Make sure that code that uses the optimized bit syntax matching "
  150: 	"can be traced without crashing the emulator.";
  151: bit_syntax(Config) when is_list(Config) ->
  152:     bit_syntax_test().
  153: 
  154: return(doc) ->
  155:     ["Tests the different types of return trace"];
  156: return(Config) when is_list(Config) ->
  157:     return_test().
  158:  
  159: on_and_off(doc) ->
  160:     ["Tests turning trace parameters on and off, "
  161:      "both for trace and trace_pattern"];
  162: on_and_off(Config) when is_list(Config) ->
  163:     on_and_off_test().
  164:  
  165: stack_grow(doc) ->
  166:     ["Tests the stack growth during return traces"];
  167: stack_grow(Config) when is_list(Config) ->
  168:     stack_grow_test().
  169:  
  170: info(doc) ->
  171:     ["Tests the trace_info BIF"];
  172: info(Config) when is_list(Config) ->
  173:     info_test().
  174:  
  175: delete(doc) ->
  176:     ["Tests putting trace on deleted modules"];
  177: delete(Config) when is_list(Config) ->
  178:     delete_test(Config).
  179: 
  180: exception(doc) ->
  181:     ["Tests exception_trace"];
  182: exception(Config) when is_list(Config) ->
  183:     exception_test([]).
  184: 
  185: exception_apply(doc) ->
  186:     ["Tests exception_trace"];
  187: exception_apply(Config) when is_list(Config) ->
  188:     exception_test([apply]).
  189: 
  190: exception_function(doc) ->
  191:     ["Tests exception_trace"];
  192: exception_function(Config) when is_list(Config) ->
  193:     exception_test([function]).
  194: 
  195: exception_apply_function(doc) ->
  196:     ["Tests exception_trace"];
  197: exception_apply_function(Config) when is_list(Config) ->
  198:     exception_test([apply,function]).
  199: 
  200: exception_nocatch(doc) ->
  201:     ["Tests exception_trace"];
  202: exception_nocatch(Config) when is_list(Config) ->
  203:     exception_test([nocatch]).
  204: 
  205: exception_nocatch_apply(doc) ->
  206:     ["Tests exception_trace"];
  207: exception_nocatch_apply(Config) when is_list(Config) ->
  208:     exception_test([nocatch,apply]).
  209: 
  210: exception_nocatch_function(doc) ->
  211:     ["Tests exception_trace"];
  212: exception_nocatch_function(Config) when is_list(Config) ->
  213:     exception_test([nocatch,function]).
  214: 
  215: exception_nocatch_apply_function(doc) ->
  216:     ["Tests exception_trace"];
  217: exception_nocatch_apply_function(Config) when is_list(Config) ->
  218:     exception_test([nocatch,apply,function]).
  219: 
  220: exception_meta(doc) ->
  221:     ["Tests meta exception_trace"];
  222: exception_meta(Config) when is_list(Config) ->
  223:     exception_test([meta]).
  224: 
  225: exception_meta_apply(doc) ->
  226:     ["Tests meta exception_trace"];
  227: exception_meta_apply(Config) when is_list(Config) ->
  228:     exception_test([meta,apply]).
  229: 
  230: exception_meta_function(doc) ->
  231:     ["Tests meta exception_trace"];
  232: exception_meta_function(Config) when is_list(Config) ->
  233:     exception_test([meta,function]).
  234: 
  235: exception_meta_apply_function(doc) ->
  236:     ["Tests meta exception_trace"];
  237: exception_meta_apply_function(Config) when is_list(Config) ->
  238:     exception_test([meta,apply,function]).
  239: 
  240: exception_meta_nocatch(doc) ->
  241:     ["Tests meta exception_trace"];
  242: exception_meta_nocatch(Config) when is_list(Config) ->
  243:     exception_test([meta,nocatch]).
  244: 
  245: exception_meta_nocatch_apply(doc) ->
  246:     ["Tests meta exception_trace"];
  247: exception_meta_nocatch_apply(Config) when is_list(Config) ->
  248:     exception_test([meta,nocatch,apply]).
  249: 
  250: exception_meta_nocatch_function(doc) ->
  251:     ["Tests meta exception_trace"];
  252: exception_meta_nocatch_function(Config) when is_list(Config) ->
  253:     exception_test([meta,nocatch,function]).
  254: 
  255: exception_meta_nocatch_apply_function(doc) ->
  256:     ["Tests meta exception_trace"];
  257: exception_meta_nocatch_apply_function(Config) when is_list(Config) ->
  258:     exception_test([meta,nocatch,apply,function]).
  259: 
  260: -endif.
  261: 
  262: 
  263: 
  264: %%% Message patterns and expect functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  265: 
  266: -define(pCT(P,M,F,A),   {trace,   P,call,{M,F,A}}).
  267: -define(pCTT(P,M,F,A),  {trace_ts,P,call,{M,F,A},{_,_,_}}).
  268: -define(pRF(P,M,F,A,V), {trace,   P,return_from,{M,F,A},V}).
  269: -define(pRFT(P,M,F,A,V),{trace_ts,P,return_from,{M,F,A},V,{_,_,_}}).
  270: -define(pEF(P,M,F,A,V), {trace,   P,exception_from,{M,F,A},V}).
  271: -define(pEFT(P,M,F,A,V),{trace_ts,P,exception_from,{M,F,A},V,{_,_,_}}).
  272: -define(pRT(P,M,F,A),   {trace,   P,return_to,{M,F,A}}).
  273: -define(pRTT(P,M,F,A),  {trace_ts,P,return_to,{M,F,A},{_,_,_}}).
  274: 
  275: -define(CT(M,F,A),    ?pCT(_,M,F,A)    = receive_next()).
  276: -define(CTT(M,F,A),   ?pCTT(_,M,F,A)   = receive_next()).
  277: -define(RF(M,F,A,V),  ?pRF(_,M,F,A,V)  = receive_next()).
  278: -define(RFT(M,F,A,V), ?pRFT(_,M,F,A,V) = receive_next()).
  279: -define(EF(M,F,A,V),  ?pEF(_,M,F,A,V)  = receive_next()).
  280: -define(EFT(M,F,A,V), ?pEFT(_,M,F,A,V) = receive_next()).
  281: -define(RT(M,F,A),    ?pRT(_,M,F,A)    = receive_next()).
  282: -define(RTT(M,F,A),   ?pRTT(_,M,F,A)   = receive_next()).
  283: -define(NM, receive_no_next(100)).
  284: 
  285: expect() ->
  286:     {Pid,_} = get(slave),
  287:     expect_receive(Pid).
  288: 
  289: expect(Msg) ->
  290:     {Pid,_} = get(slave),
  291:     expect_pid(Pid, Msg).
  292: 
  293: 
  294: 
  295: expect_pid(_Pid, []) ->
  296:     ok;
  297: expect_pid(Pid, [Line|T]) when is_integer(Line) ->
  298:     put(test_server_loc, {?MODULE,Line}),
  299:     expect_pid(Pid, T);
  300: expect_pid(Pid, [true|[_|_]=T]) ->
  301:     expect_pid(Pid, T);
  302: expect_pid(Pid, [false|[_|T]]) ->
  303:     expect_pid(Pid, T);
  304: expect_pid(Pid, [H|T]) ->
  305:     expect_pid(Pid, H),
  306:     expect_pid(Pid, T);
  307: expect_pid(Pid, Msg) when is_tuple(Msg) ->
  308:     same(Msg, expect_receive(Pid));
  309: expect_pid(Pid, Fun) when is_function(Fun, 1) ->
  310:     case Fun(expect_receive(Pid)) of
  311: 	next ->
  312: 	    expect_pid(Pid, Fun);
  313: 	done ->
  314: 	    ok;
  315: 	Other ->
  316: 	    expect_pid(Pid, Other)
  317:     end.
  318: 
  319: expect_receive(Pid) when is_pid(Pid) ->
  320:     receive
  321: 	Msg when is_tuple(Msg), 
  322: 		 element(1, Msg) == trace, 
  323: 		 element(2, Msg) =/= Pid;
  324: 		 %%
  325: 		 is_tuple(Msg), 
  326: 		 element(1, Msg) == trace_ts, 
  327: 		 element(2, Msg) =/= Pid ->
  328: 	    expect_receive(Pid);
  329: 	Msg ->
  330: 	    expect_msg(Pid, Msg)
  331:     after 100 ->
  332: 	    {nm}
  333:     end.
  334: 
  335: expect_msg(P, ?pCT(P,M,F,Args))       -> {ct,{M,F},Args};
  336: expect_msg(P, ?pCTT(P,M,F,Args))      -> {ctt,{M,F},Args};
  337: expect_msg(P, ?pRF(P,M,F,Arity,V))    -> {rf,{M,F,Arity},V};
  338: expect_msg(P, ?pRFT(P,M,F,Arity,V))   -> {rft,{M,F,Arity},V};
  339: expect_msg(P, ?pEF(P,M,F,Arity,V))    -> {ef,{M,F,Arity},V};
  340: expect_msg(P, ?pEFT(P,M,F,Arity,V))   -> {eft,{M,F,Arity},V};
  341: expect_msg(P, ?pRT(P,M,F,Arity))      -> {rt,{M,F,Arity}};
  342: expect_msg(P, ?pRTT(P,M,F,Arity))     -> {rtt,{M,F,Arity}};
  343: expect_msg(P, Msg) when is_tuple(Msg) ->
  344:     case tuple_to_list(Msg) of
  345: 	[trace,P|T] ->
  346: 	    list_to_tuple([trace|T]);
  347: 	[trace_ts,P|[_|_]=T] ->
  348: 	    list_to_tuple([trace_ts|reverse(tl(reverse(T)))]);
  349: 	_ ->
  350: 	    Msg
  351:     end.
  352: 
  353: same(A, B) ->
  354:     case [A|B] of
  355: 	[X|X] ->
  356: 	    ok
  357:     end.
  358: 
  359: 
  360: 
  361: %%% tests %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  362: 
  363: basic_test() ->
  364:     ?line setup([call]),
  365:     NumMatches = erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
  366:     NumMatches = erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
  367:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
  368:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  369:     ?line ?CT(?MODULE,exported_wrap,[1]),
  370:     ?line ?CT(?MODULE,exported,[1]),
  371:     ?line ?CT(?MODULE,local,[1]),
  372:     ?line ?CT(?MODULE,local2,[1]),
  373:     ?line ?CT(?MODULE,local_tail,[1]),
  374:     ?line erlang:trace_pattern({?MODULE,'_','_'},[],[]),
  375:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
  376:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  377:     ?line ?CT(?MODULE,exported_wrap,[1]),
  378:     ?line [1,1,1,1] = lambda_slave(fun() ->
  379: 					   exported_wrap(1)
  380: 				   end),
  381:     ?line ?NM, 
  382:     ?line erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
  383:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
  384:     ?line [1,1,1,1] = lambda_slave(fun() ->
  385: 					   exported_wrap(1)
  386: 				   end),
  387:     ?line ?CT(?MODULE,_,_), %% The fun
  388:     ?line ?CT(?MODULE,exported_wrap,[1]),
  389:     ?line ?CT(?MODULE,exported,[1]),
  390:     ?line ?CT(?MODULE,local,[1]),
  391:     ?line ?CT(?MODULE,local2,[1]),
  392:     ?line ?CT(?MODULE,local_tail,[1]),
  393:     ?line erlang:trace_pattern({?MODULE,'_','_'},false,[local]),
  394:     ?line shutdown(),
  395:     ?line ?NM,
  396:     ok.
  397: 
  398: %% OTP-7399.
  399: bit_syntax_test() ->
  400:     ?line setup([call]),
  401:     ?line erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
  402:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
  403: 
  404:     ?line lambda_slave(fun() ->
  405: 			       6 = bs_sum_a(<<1,2,3>>, 0),
  406: 			       10 = bs_sum_b(0, <<1,2,3,4>>),
  407: 			       26 = bs_sum_c(<<3:4,5:4,7:4,11:4>>, 0)
  408: 		       end),
  409:     ?line ?CT(?MODULE,_,[]),		      %Ignore call to the fun.
  410: 
  411:     ?line ?CT(?MODULE,bs_sum_a,[<<1,2,3>>,0]),
  412:     ?line ?CT(?MODULE,bs_sum_a,[<<2,3>>,1]),
  413:     ?line ?CT(?MODULE,bs_sum_a,[<<3>>,3]),
  414:     ?line ?CT(?MODULE,bs_sum_a,[<<>>,6]),
  415: 
  416:     ?line ?CT(?MODULE,bs_sum_b,[0,<<1,2,3,4>>]),
  417:     ?line ?CT(?MODULE,bs_sum_b,[1,<<2,3,4>>]),
  418:     ?line ?CT(?MODULE,bs_sum_b,[3,<<3,4>>]),
  419:     ?line ?CT(?MODULE,bs_sum_b,[6,<<4>>]),
  420:     ?line ?CT(?MODULE,bs_sum_b,[10,<<>>]),
  421: 
  422:     ?line ?CT(?MODULE,bs_sum_c,[<<3:4,5:4,7:4,11:4>>, 0]),
  423:     ?line ?CT(?MODULE,bs_sum_c,[<<5:4,7:4,11:4>>, 3]),
  424:     ?line ?CT(?MODULE,bs_sum_c,[<<7:4,11:4>>, 8]),
  425:     ?line ?CT(?MODULE,bs_sum_c,[<<11:4>>, 15]),
  426:     ?line ?CT(?MODULE,bs_sum_c,[<<>>, 26]),
  427: 
  428:     ?line erlang:trace_pattern({?MODULE,'_','_'},false,[local]),
  429:     ?line shutdown(),
  430:     ?line ?NM,
  431: 
  432:     ok.
  433: 
  434: bs_sum_a(<<H,T/binary>>, Acc) -> bs_sum_a(T, H+Acc);
  435: bs_sum_a(<<>>, Acc) -> Acc.
  436: 
  437: bs_sum_b(Acc, <<H,T/binary>>) -> bs_sum_b(H+Acc, T);
  438: bs_sum_b(Acc, <<>>) -> Acc.
  439: 
  440: bs_sum_c(<<H:4,T/bits>>, Acc) -> bs_sum_c(T, H+Acc);
  441: bs_sum_c(<<>>, Acc) -> Acc.
  442: 
  443: return_test() ->
  444:     ?line setup([call]),
  445:     ?line erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}],
  446: 			 [local]),
  447:     ?line erlang:trace_pattern({erlang,hash,'_'},[{'_',[],[{return_trace}]}],
  448: 			 [local]),
  449:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
  450:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  451:     ?line ?CT(?MODULE,exported_wrap,[1]), 
  452:     ?line ?CT(?MODULE,exported,[1]),
  453:     ?line ?CT(?MODULE,local,[1]),
  454:     ?line ?CT(?MODULE,local2,[1]),
  455:     ?line ?CT(?MODULE,local_tail,[1]),
  456:     ?line ?CT(erlang,hash,[1,1]),
  457:     ?line ?RF(erlang,hash,2,1),
  458:     ?line ?RF(?MODULE,local_tail,1,[1,1]),
  459:     ?line ?RF(?MODULE,local2,1,[1,1]),
  460:     ?line ?RF(?MODULE,local,1,[1,1,1]),
  461:     ?line ?RF(?MODULE,exported,1,[1,1,1,1]),
  462:     ?line ?RF(?MODULE,exported_wrap,1,[1,1,1,1]),
  463:     ?line shutdown(),
  464:     ?line setup([call,return_to]),
  465:     ?line erlang:trace_pattern({?MODULE,'_','_'},[],
  466: 			       [local]),
  467:     ?line erlang:trace_pattern({erlang,hash,'_'},[],
  468: 			       [local]),
  469:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
  470:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  471:     ?line ?CT(?MODULE,exported_wrap,[1]), 
  472:     ?line ?CT(?MODULE,exported,[1]),
  473:     ?line ?CT(?MODULE,local,[1]),
  474:     ?line ?CT(?MODULE,local2,[1]),
  475:     ?line ?CT(?MODULE,local_tail,[1]),
  476:     ?line ?CT(erlang,hash,[1,1]),
  477:     ?line ?RT(?MODULE,local_tail,1),
  478:     ?line ?RT(?MODULE,local,1),
  479:     ?line ?RT(?MODULE,exported,1),
  480:     ?line ?RT(?MODULE,slave,2),
  481:     ?line shutdown(),
  482:     ?line setup([call,return_to]),
  483:     ?line erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}],
  484: 			       [local]),
  485:     ?line erlang:trace_pattern({erlang,hash,'_'},[{'_',[],[{return_trace}]}],
  486: 			       [local]),
  487:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
  488:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  489:     ?line ?CT(?MODULE,exported_wrap,[1]), 
  490:     ?line ?CT(?MODULE,exported,[1]),
  491:     ?line ?CT(?MODULE,local,[1]),
  492:     ?line ?CT(?MODULE,local2,[1]),
  493:     ?line ?CT(?MODULE,local_tail,[1]),
  494:     ?line ?CT(erlang,hash,[1,1]),
  495:     ?line ?RF(erlang,hash,2,1),
  496:     ?line ?RT(?MODULE,local_tail,1),
  497:     ?line ?RF(?MODULE,local_tail,1,[1,1]),
  498:     ?line ?RF(?MODULE,local2,1,[1,1]),
  499:     ?line ?RT(?MODULE,local,1),
  500:     ?line ?RF(?MODULE,local,1,[1,1,1]),
  501:     ?line ?RT(?MODULE,exported,1),
  502:     ?line ?RF(?MODULE,exported,1,[1,1,1,1]),
  503:     ?line ?RF(?MODULE,exported_wrap,1,[1,1,1,1]),
  504:     ?line ?RT(?MODULE,slave,2),
  505:     ?line shutdown(),
  506:     ?line ?NM,
  507:     ok.
  508: 
  509: on_and_off_test() ->
  510:     ?line Pid = setup([call]),
  511:     ?line 1 = erlang:trace_pattern({?MODULE,local_tail,1},[],[local]),
  512:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
  513:     ?line LocalTail = fun() ->
  514: 			      local_tail(1)
  515: 		      end,
  516:     ?line [1,1] = lambda_slave(LocalTail),
  517:     ?line ?CT(?MODULE,local_tail,[1]),
  518:     ?line erlang:trace(Pid,true,[return_to]),
  519:     ?line [1,1] = lambda_slave(LocalTail),
  520:     ?line ?CT(?MODULE,local_tail,[1]),
  521:     ?line ?RT(?MODULE,_,_),
  522:     ?line 0 = erlang:trace_pattern({?MODULE,local_tail,1},[],[global]),
  523:     ?line [1,1] = lambda_slave(LocalTail),
  524:     ?line ?NM,
  525:     ?line 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[global]),
  526:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  527:     ?line ?CT(?MODULE,exported_wrap,[1]),
  528:     ?line 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[local]),
  529:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  530:     ?line ?CT(?MODULE,exported_wrap,[1]),
  531:     ?line ?RT(?MODULE,slave,2),
  532:     ?line 1 = erlang:trace_pattern({erlang,hash,2},[],[local]),
  533:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  534:     ?line ?CT(?MODULE,exported_wrap,[1]),
  535:     ?line ?CT(erlang,hash,[1,1]),
  536:     ?line ?RT(?MODULE,local_tail,1),
  537:     ?line ?RT(?MODULE,slave,2),
  538:     ?line erlang:trace(Pid,true,[timestamp]),
  539:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  540:     ?line ?CTT(?MODULE,exported_wrap,[1]),
  541:     ?line ?CTT(erlang,hash,[1,1]),
  542:     ?line ?RTT(?MODULE,local_tail,1),
  543:     ?line ?RTT(?MODULE,slave,2),
  544:     ?line erlang:trace(Pid,false,[return_to,timestamp]),
  545:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  546:     ?line ?CT(?MODULE,exported_wrap,[1]),
  547:     ?line ?CT(erlang,hash,[1,1]),
  548:     ?line erlang:trace(Pid,true,[return_to]),
  549:     ?line 1 = erlang:trace_pattern({erlang,hash,2},[],[]),
  550:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  551:     ?line ?CT(?MODULE,exported_wrap,[1]),
  552:     ?line ?CT(erlang,hash,[1,1]),
  553:     ?line ?RT(?MODULE,slave,2),
  554:     ?line 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[]),
  555:     ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
  556:     ?line ?CT(?MODULE,exported_wrap,[1]),
  557:     ?line ?CT(erlang,hash,[1,1]),
  558:     ?line shutdown(),
  559:     ?line erlang:trace_pattern({'_','_','_'},false,[local]),
  560:     ?line N = erlang:trace_pattern({erlang,'_','_'},true,[local]),
  561:     ?line case erlang:trace_pattern({erlang,'_','_'},false,[local]) of
  562: 	      N -> 
  563: 		  ok;
  564: 	      Else ->
  565: 		  exit({number_mismatch, {expected, N}, {got, Else}})
  566: 	  end,
  567:     ?line case erlang:trace_pattern({erlang,'_','_'},false,[local]) of
  568: 	      N -> 
  569: 		  ok;
  570: 	      Else2 ->
  571: 		  exit({number_mismatch, {expected, N}, {got, Else2}})
  572: 	  end,
  573:     ?line M = erlang:trace_pattern({erlang,'_','_'},true,[]),
  574:     ?line case erlang:trace_pattern({erlang,'_','_'},false,[]) of
  575: 	      M -> 
  576: 		  ok;
  577: 	      Else3 ->
  578: 		  exit({number_mismatch, {expected, N}, {got, Else3}})
  579: 	  end,
  580:     ?line case erlang:trace_pattern({erlang,'_','_'},false,[]) of
  581: 	      M -> 
  582: 		  ok;
  583: 	      Else4 ->
  584: 		  exit({number_mismatch, {expected, N}, {got, Else4}})
  585: 	  end,
  586:     ?line ?NM,
  587:     ok.
  588: 
  589: systematic_on_off(Config) when is_list(Config) ->
  590:     setup([call]),
  591:     Local = combinations([local,meta,call_count,call_time]),
  592:     [systematic_on_off_1(Flags) || Flags <- Local],
  593: 
  594:     %% Make sure that we don't get any trace messages when trace
  595:     %% is supposed to be off.
  596:     receive_no_next(500).
  597: 
  598: systematic_on_off_1(Local) ->
  599:     io:format("~p\n", [Local]),
  600: 
  601:     %% Global off.
  602:     verify_trace_info(false, []),
  603:     1 = erlang:trace_pattern({?MODULE,exported_wrap,1}, true, Local),
  604:     verify_trace_info(false, Local),
  605:     1 = erlang:trace_pattern({?MODULE,exported_wrap,1}, false, [global]),
  606:     verify_trace_info(false, Local),
  607:     1 = erlang:trace_pattern({?MODULE,exported_wrap,1}, false, Local),
  608:     verify_trace_info(false, []),
  609: 
  610:     %% Global on.
  611:     1 = erlang:trace_pattern({?MODULE,exported_wrap,1}, true, [global]),
  612:     verify_trace_info(true, []),
  613:     1 = erlang:trace_pattern({?MODULE,exported_wrap,1}, false, Local),
  614:     verify_trace_info(true, []),
  615:     1 = erlang:trace_pattern({?MODULE,exported_wrap,1}, false, [global]),
  616:     verify_trace_info(false, []),
  617: 
  618:     %% Implicitly turn off global call trace.
  619:     1 = erlang:trace_pattern({?MODULE,exported_wrap,1}, true, [global]),
  620:     verify_trace_info(true, []),
  621:     1 = erlang:trace_pattern({?MODULE,exported_wrap,1}, true, Local),
  622:     verify_trace_info(false, Local),
  623: 
  624:     %% Implicitly turn off local call trace.
  625:     1 = erlang:trace_pattern({?MODULE,exported_wrap,1}, true, [global]),
  626:     verify_trace_info(true, []),
  627: 
  628:     %% Turn off global call trace. Everything should be off now.
  629:     1 = erlang:trace_pattern({?MODULE,exported_wrap,1}, false, [global]),
  630:     verify_trace_info(false, []),
  631: 
  632:     ok.
  633: 
  634: verify_trace_info(Global, Local) ->
  635:     case erlang:trace_info({?MODULE,exported_wrap,1}, all) of
  636: 	{all,false} ->
  637: 	    false = Global,
  638: 	    [] = Local;
  639: 	{all,Ps} ->
  640: 	    io:format("~p\n", [Ps]),
  641: 	    [verify_trace_info(P, Global, Local) || P <- Ps]
  642:     end,
  643:     global_call(Global, Local),
  644:     local_call(Local),
  645:     ok.
  646: 
  647: verify_trace_info({traced,global}, true, []) -> ok;
  648: verify_trace_info({traced,local}, false, _) -> ok;
  649: verify_trace_info({match_spec,[]}, _, _) -> ok;
  650: verify_trace_info({meta_match_spec,[]}, _, _) -> ok;
  651: verify_trace_info({LocalFlag,Bool}, _, Local) when is_boolean(Bool) ->
  652:     try
  653: 	Bool = lists:member(LocalFlag, Local)
  654:     catch
  655: 	error:_ ->
  656: 	    io:format("Line ~p: {~p,~p}, false, ~p\n",
  657: 		      [?LINE,LocalFlag,Bool,Local]),
  658: 	    ?t:fail()
  659:     end;
  660: verify_trace_info({meta,Pid}, false, Local) when is_pid(Pid) ->
  661:     true = lists:member(meta, Local);
  662: verify_trace_info({call_time,_}, false, Local) ->
  663:     true = lists:member(call_time, Local);
  664: verify_trace_info({call_count,_}, false, Local) ->
  665:     true = lists:member(call_time, Local).
  666: 
  667: global_call(Global, Local) ->
  668:     apply_slave(?MODULE, exported_wrap, [global_call]),
  669:     case Global of
  670: 	false ->
  671: 	    recv_local_call(Local, [global_call]);
  672: 	true ->
  673: 	    ?CT(?MODULE, exported_wrap, [global_call])
  674:     end.
  675: 
  676: local_call(Local) ->
  677:     lambda_slave(fun() -> exported_wrap(local_call) end),
  678:     recv_local_call(Local, [local_call]).
  679: 
  680: recv_local_call(Local, Args) ->
  681:     case lists:member(local, Local) of
  682: 	false ->
  683: 	    ok;
  684: 	true ->
  685: 	    ?CT(?MODULE, exported_wrap, Args)
  686:     end,
  687:     case lists:member(meta, Local) of
  688: 	false ->
  689: 	    ok;
  690: 	true ->
  691: 	    ?CTT(?MODULE, exported_wrap, Args)
  692:     end,
  693:     ok.
  694: 
  695: combinations([_]=One) ->
  696:     [One];
  697: combinations([H|T]) ->
  698:     Cs = combinations(T),
  699:     [[H|C] || C <- Cs] ++ Cs.
  700:     
  701: stack_grow_test() ->    
  702:     ?line setup([call,return_to]),
  703:     ?line 1 = erlang:trace_pattern({?MODULE,loop,4},
  704: 				   [{'_',[],[{return_trace}]}],[local]),
  705:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
  706:     ?line Num = 1 bsl 15,
  707:     ?line Fun = 
  708: 	fun(_F,0) -> ok; 
  709: 	   (F,N) -> 
  710: 		receive _A -> 
  711: 			receive _B -> 
  712: 				receive _C ->
  713: 					F(F,N-1) 
  714: 				end
  715: 			end 
  716: 		end 
  717: 	end, 
  718:     ?line apply_slave_async(?MODULE,loop,[{hej,hopp},[a,b,c],4.5,Num]),
  719:     ?line Fun(Fun,Num + 1),
  720:     ?line ?NM, 
  721:     ok.
  722: 
  723: 
  724: info_test() ->
  725:     ?line Flags1 = lists:sort([call,return_to]),
  726:     ?line Pid = setup(Flags1),
  727:     ?line Prog = [{['$1'],[{is_integer,'$1'}],[{message, false}]},
  728: 		  {'_',[],[]}],
  729:     ?line erlang:trace_pattern({?MODULE,exported_wrap,1},Prog,[local]),
  730:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
  731:     ?line Self = self(),
  732:     ?line {flags,L} = erlang:trace_info(Pid,flags),
  733:     ?line case lists:sort(L) of
  734: 	      Flags1 ->
  735: 		  ok;
  736: 	      Wrong1 ->
  737: 		  exit({bad_result, {erlang,trace_info,[Pid,flags]},
  738: 			{expected, Flags1}, {got, Wrong1}})
  739: 	  end,
  740:     ?line {tracer,Tracer} = erlang:trace_info(Pid,tracer),
  741:     ?line case Tracer of
  742: 	      Self ->
  743: 		  ok;
  744: 	      Wrong2 ->
  745: 		  exit({bad_result, {erlang,trace_info,[Pid,tracer]},
  746: 			{expected, Self}, {got, Wrong2}})
  747: 	  end,
  748:     ?line {traced,local} = erlang:trace_info({?MODULE,exported_wrap,1},traced),
  749:     ?line {match_spec, MS} = 
  750: 	erlang:trace_info({?MODULE,exported_wrap,1},match_spec),
  751:     ?line case MS of
  752: 	      Prog ->
  753: 		  ok;
  754: 	      Wrong3 ->
  755: 		  exit({bad_result, {erlang,trace_info,
  756: 				     [{?MODULE,exported_wrap,1},
  757: 				      match_spec]},
  758: 			{expected, Prog}, {got, Wrong3}})
  759: 	  end,
  760:     ?line erlang:garbage_collect(self()),
  761:     ?line receive
  762: 	  after 1 ->
  763: 		  ok
  764: 	  end,
  765:     ?line io:format("~p~n",[MS]),
  766:     ?line {match_spec,MS2} = 
  767: 	erlang:trace_info({?MODULE,exported_wrap,1},match_spec),
  768:     ?line io:format("~p~n",[MS2]),
  769:     ?line erlang:trace_pattern({?MODULE,exported_wrap,1},[],[]),
  770:     ?line {traced,global} = 
  771: 	erlang:trace_info({?MODULE,exported_wrap,1},traced),
  772:     ?line {match_spec,[]} = 
  773: 	erlang:trace_info({?MODULE,exported_wrap,1},match_spec),
  774:     ?line {traced,undefined} = 
  775: 	erlang:trace_info({?MODULE,exported_wrap,2},traced),
  776:     ?line {match_spec,undefined} = 
  777: 	erlang:trace_info({?MODULE,exported_wrap,2},match_spec),
  778:     ?line {traced,false} = erlang:trace_info({?MODULE,exported,1},traced),
  779:     ?line {match_spec,false} = 
  780: 	erlang:trace_info({?MODULE,exported,1},match_spec),
  781:     ?line shutdown(),
  782:     ok.
  783: 
  784: delete_test(Config) ->
  785:     ?line Priv = ?config(priv_dir, Config),
  786:     ?line Data = ?config(data_dir, Config),
  787:     ?line File = filename:join(Data, "trace_local_dummy"),
  788:     ?line {ok,trace_local_dummy} = c:c(File, [{outdir,Priv}]),
  789:     ?line code:purge(trace_local_dummy),
  790:     ?line code:delete(trace_local_dummy),
  791:     ?line 0 = erlang:trace_pattern({trace_local_dummy,'_','_'},true,[local]),
  792:     ?line ?NM,
  793:     ok.
  794: 
  795: 
  796: 
  797: %%% exception_test %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  798: 
  799: exception_test(Opts) ->
  800:     ?line {ProcFlags,PatFlags} = 
  801: 	case proplists:get_bool(meta, Opts) of
  802: 	    true  -> {[timestamp],[meta]};
  803: 	    false -> {[call,return_to,timestamp],[local]}
  804: 	end,
  805:     ?line case proplists:get_bool(nocatch, Opts) of
  806: 	      false ->
  807: 		  ?line Exceptions = exceptions(),
  808: 		  ?line exception_test_setup(ProcFlags, PatFlags),
  809: 		  ?line lists:foreach(
  810: 			  fun ({Func,Args}) ->
  811: 				  ?line exception_test(Opts, Func, Args)
  812: 			  end,
  813: 			  Exceptions),
  814: 		  ?line shutdown();
  815: 	      true ->
  816: 		  ?line Exceptions = exceptions(),
  817: 		  ?line lists:foreach(
  818: 			  fun ({Func,Args}) ->
  819: 				  ?line exception_test_setup(
  820: 					  [procs|ProcFlags],
  821: 					  PatFlags),
  822: 				  ?line exception_test(Opts, Func, Args),
  823: 				  ?line shutdown()
  824: 			  end,
  825: 			  Exceptions)
  826: 	  end,
  827:     ?line ok.
  828: 
  829: exceptions() ->
  830:     Ref = make_ref(),
  831:     N   = 200000,
  832:     LiL = seq(1, N-1, N),	% Long Improper List
  833:     LL  = seq(1, N, []),  	% Long List
  834:     [{{erlang,exit},  [done]},
  835:      {{erlang,error}, [1.0]},
  836:      {{erlang,error}, [Ref,[]]},
  837:      {{erlang,throw}, [4711]},
  838:      {{erlang,'++'},    [[17],seventeen]},
  839:      {{erlang,'++'},    [Ref,[125.125]]},
  840:      {{?MODULE,match},  [ref,Ref]},
  841:      {{?MODULE,match},  [Ref,Ref]},
  842:      {{?MODULE,clause}, [ref,Ref]},
  843:      {{?MODULE,clause}, [Ref,Ref]},
  844:      {{?MODULE,id},     [4711.0]},
  845:      {{?MODULE,undef},  [[Ref|Ref]]},
  846:      {{?MODULE,lists_reverse}, [LiL,[]]},
  847:      {{?MODULE,lists_reverse}, [LL,[]]}].
  848: 
  849: exception_test_setup(ProcFlags, PatFlags) ->
  850:     ?line Pid = setup(ProcFlags),
  851:     ?line io:format("=== exception_test_setup(~p, ~p): ~p~n", 
  852: 		    [ProcFlags,PatFlags,Pid]),
  853:     ?line Mprog = [{'_',[],[{exception_trace}]}],
  854:     ?line erlang:trace_pattern({?MODULE,'_','_'}, Mprog, PatFlags),
  855:     ?line erlang:trace_pattern({?MODULE,slave,'_'},false,PatFlags),
  856:     ?line [1,1,1,1,1] =
  857: 	[erlang:trace_pattern({erlang,F,A}, Mprog, PatFlags)
  858: 	 || {F,A} <- [{exit,1},{error,1},{error,2},{throw,1},{'++',2}]],
  859:     ?line 1 = erlang:trace_pattern({lists,reverse,2}, Mprog, PatFlags),
  860:     ?line ok.
  861: 
  862: -record(exc_opts, {nocatch=false, meta=false}).
  863: 
  864: exception_test(Opts, Func0, Args0) ->
  865:     ?line io:format("=== exception_test(~p, ~p, ~p)~n", 
  866: 		    [Opts,Func0,abbr(Args0)]),
  867:     ?line Apply = proplists:get_bool(apply, Opts),
  868:     ?line Function = proplists:get_bool(function, Opts),
  869:     ?line Nocatch = proplists:get_bool(nocatch, Opts),
  870:     ?line Meta = proplists:get_bool(meta, Opts),
  871:     ?line ExcOpts = #exc_opts{nocatch=Nocatch,meta=Meta},
  872:     
  873:     %% Func0 and Args0 are for the innermost call, now we will
  874:     %% wrap them in wrappers...
  875:     ?line {Func1,Args1} =
  876: 	case Function of
  877: 	    true  -> {fun exc/2,[Func0,Args0]};
  878: 	    false -> {Func0,Args0}
  879: 	end,
  880:     
  881:     ?line {Func,Args} = 
  882: 	case Apply of
  883: 	    true  -> {{erlang,apply},[Func1,Args1]};
  884: 	    false -> {Func1,Args1}
  885: 	end,
  886:     
  887:     ?line R1 = exc_slave(ExcOpts, Func, Args),
  888:     ?line Stack2 = [{?MODULE,exc_top,3,[]},{?MODULE,slave,2,[]}],
  889:     ?line Stack3 = [{?MODULE,exc,2,[]}|Stack2],
  890:     ?line Rs = 
  891: 	case x_exc_top(ExcOpts, Func, Args) of % Emulation
  892: 	    {crash,{Reason,Stack}}=R when is_list(Stack) ->
  893: 		[R,
  894: 		 {crash,{Reason,Stack++Stack2}},
  895: 		 {crash,{Reason,Stack++Stack3}}];
  896: 	    R ->
  897: 		[R]
  898: 	end,
  899:     ?line exception_validate(R1, Rs),
  900:     ?line case R1 of
  901: 	      {crash,Crash} ->
  902: 		  ?line expect({trace_ts,exit,Crash});
  903: 	      _ when not Meta ->
  904: 		  ?line expect({rtt,{?MODULE,slave,2}});
  905: 	      _ ->
  906: 		  ok
  907: 	  end,
  908:     ?line expect({nm}).
  909: 
  910: exception_validate(R0, Rs0) ->
  911:     R = clean_location(R0),
  912:     Rs = [clean_location(E) || E <- Rs0],
  913:     exception_validate_1(R, Rs).
  914: 
  915: exception_validate_1(R1, [R2|Rs]) ->
  916:     case [R1|R2] of
  917: 	[R|R] ->
  918: 	    ok;
  919: 	[{crash,{badarg,[{lists,reverse,[L1a,L1b],_}|T]}}|
  920: 	 {crash,{badarg,[{lists,reverse,[L2a,L2b],_}|T]}}] ->
  921: 	    same({crash,{badarg,[{lists,reverse,
  922: 				  [lists:reverse(L1b, L1a),[]],[]}|T]}},
  923: 		 {crash,{badarg,[{lists,reverse,
  924: 				  [lists:reverse(L2b, L2a),[]],[]}|T]}});
  925: 	_ when is_list(Rs), Rs =/= [] ->
  926: 	    exception_validate(R1, Rs)
  927:     end.
  928: 
  929: clean_location({crash,{Reason,Stk0}}) ->
  930:     Stk = [{M,F,A,[]} || {M,F,A,_} <- Stk0],
  931:     {crash,{Reason,Stk}};
  932: clean_location(Term) -> Term.
  933: 
  934: concurrency(_Config) ->
  935:     N = erlang:system_info(schedulers),
  936: 
  937:     %% Spawn 2*N processes that spin in a tight infinite loop,
  938:     %% and one process that will turn on and off local call
  939:     %% trace on the infinite_loop/0 function. We expect the
  940:     %% emulator to crash if there is a memory barrier bug or
  941:     %% if an aligned word-sized write is not atomic.
  942: 
  943:     Ps0 = [spawn_monitor(fun() -> infinite_loop() end) ||
  944: 	      _ <- lists:seq(1, 2*N)],
  945:     OnAndOff = fun() -> concurrency_on_and_off() end,
  946:     Ps1 = [spawn_monitor(OnAndOff)|Ps0],
  947:     ?t:sleep(1000),
  948: 
  949:     %% Now spawn off N more processes that turn on off and off
  950:     %% a local trace pattern.
  951:     Ps = [spawn_monitor(OnAndOff) || _ <- lists:seq(1, N)] ++ Ps1,
  952:     ?t:sleep(1000),
  953: 
  954:     %% Clean up.
  955:     [exit(Pid, kill) || {Pid,_} <- Ps],
  956:     [receive
  957: 	 {'DOWN',Ref,process,Pid,killed} -> ok
  958:      end || {Pid,Ref} <- Ps],
  959:     erlang:trace_pattern({?MODULE,infinite_loop,0}, false, [local]),
  960:     ok.
  961: 
  962: concurrency_on_and_off() ->
  963:     1 = erlang:trace_pattern({?MODULE,infinite_loop,0}, true, [local]),
  964:     1 = erlang:trace_pattern({?MODULE,infinite_loop,0}, false, [local]),
  965:     concurrency_on_and_off().
  966: 
  967: infinite_loop() ->
  968:     infinite_loop().
  969: 
  970: %%% Tracee target functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  971: %%%
  972: 
  973: loop(D1,D2,D3,0) ->
  974:     io:format("~p~n",[[D1,D2,D3]]),
  975:     0;
  976: loop(D1,D2,D3,N) ->
  977:     max(N,loop(D1,D2,D3,N-1)).
  978: 
  979: exported_wrap(Val) ->
  980:     exported(Val).
  981: 
  982: exported(Val) ->
  983:     [Val | local(Val)]. %% Non tail recursive local call
  984: 
  985: local(Val) ->
  986:     [Val | local2(Val)]. %% Non tail recursive local call
  987: 
  988: local2(Val) ->
  989:     local_tail(Val). %% Tail recursive call
  990: 
  991: local_tail(Val) ->
  992:     [Val , erlang:hash(1,1)].
  993: 
  994: 
  995: 
  996: %%% exc_slave/3 tracee target functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  997: %%%
  998: 
  999: exc_top(ExcOpts, Func, Args) ->
 1000:     case ExcOpts#exc_opts.nocatch of
 1001: 	false ->
 1002: 	    try exc_jump(Func, Args) of
 1003: 		Value ->
 1004: 		    {value,Value}
 1005: 	    catch
 1006: 		Class:Reason ->
 1007: 		    {Class,Reason}
 1008: 	    end;
 1009: 	true ->
 1010: 	    {value,exc_jump(Func, Args)}
 1011:     end.
 1012: 
 1013: %% x_* functions emulate the non-x_* ones.
 1014: %% x_* functions below x_exc_top
 1015: %% return {value,Value} or {Class,Reason}.
 1016: %% The only possible place for exception
 1017: %% is below exc/2.
 1018: x_exc_top(ExcOpts, Func, Args) ->
 1019:     ?line Rtt = not ExcOpts#exc_opts.meta,
 1020:     ?line expect({ctt,{?MODULE,exc_top},[ExcOpts,Func,Args]}),
 1021:     ?line case x_exc_jump(ExcOpts, Func, Args) of
 1022: 	      Result when not ExcOpts#exc_opts.nocatch ->
 1023: 		  ?line expect([Rtt,{rtt,{?MODULE,exc_top,3}},
 1024: 				?LINE,{rft,{?MODULE,exc_top,3},Result}]),
 1025: 		  ?line Result;
 1026: 	      {value,_}=Result ->
 1027: 		  
 1028: 		  ?line expect([Rtt,{rtt,{?MODULE,exc_top,3}},
 1029: 				?LINE,{rft,{?MODULE,exc_top,3},Result}]),
 1030: 		  ?line Result;
 1031: 	      {exit,Reason}=CR ->
 1032: 		  ?line expect({eft,{?MODULE,exc_top,3},CR}),
 1033: 		  ?line {crash,Reason};
 1034: 	      {error,Reason}=CR ->
 1035: 		  ?line expect({eft,{?MODULE,exc_top,3},CR}),
 1036: 		  ?line {crash,{Reason,x_exc_stacktrace()}};
 1037: 	      CR ->
 1038: 		  ?line expect({eft,{?MODULE,exc_top,3},CR}),
 1039: 		  ?line {crash,CR}
 1040: 	  end.
 1041: 
 1042: exc_jump(Func, Args) ->
 1043:     exc(Func, Args, jump).
 1044: 
 1045: x_exc_jump(ExcOpts, Func, Args) ->
 1046:     ?line expect({ctt,{?MODULE,exc_jump},[Func,Args]}),
 1047:     ?line case x_exc(ExcOpts, Func, Args, jump) of
 1048: 	      {value,Value}=Result ->
 1049: 		  ?line expect({rft,{?MODULE,exc_jump,2},Value}),
 1050: 		  ?line Result;
 1051: 	      CR ->
 1052: 		  ?line expect({eft,{?MODULE,exc_jump,2},CR}),
 1053: 		  ?line CR
 1054: 	  end.
 1055: 
 1056: exc(Func, Args, jump) ->
 1057:     exc(Func, Args, do);
 1058: exc(Func, Args, do) ->
 1059:     exc(Func, Args).
 1060: 
 1061: x_exc(ExcOpts, Func, Args, jump) ->
 1062:     ?line expect({ctt,{?MODULE,exc},[Func,Args,jump]}),
 1063:     ?line case x_exc(ExcOpts, Func, Args, do) of
 1064: 	      {value,Value}=Result ->
 1065: 		  ?line expect({rft,{?MODULE,exc,3},Value}),
 1066: 		  ?line Result;
 1067: 	      CR ->
 1068: 		  ?line expect({eft,{?MODULE,exc,3},CR}),
 1069: 		  ?line CR
 1070: 	  end;
 1071: x_exc(ExcOpts, Func, Args, do) ->
 1072:     ?line expect({ctt,{?MODULE,exc},[Func,Args,do]}),
 1073:     ?line case x_exc(ExcOpts, Func, Args) of
 1074: 	      {value,Value}=Result ->
 1075: 		  ?line expect({rft,{?MODULE,exc,3},Value}),
 1076: 		  ?line Result;
 1077: 	      CR ->
 1078: 		  ?line expect({eft,{?MODULE,exc,3},CR}),
 1079: 		  ?line CR
 1080: 	  end.
 1081: 
 1082: exc({erlang,apply}, [{M,F},A]) ->
 1083:     erlang:apply(M, F, id(A));
 1084: exc({erlang,apply}, [F,A]) ->
 1085:     erlang:apply(F, id(A));
 1086: exc({erlang,error}, [E]) ->
 1087:     erlang:error(id(E));
 1088: exc({erlang,error}, [E,S]) ->
 1089:     erlang:error(E, id(S));
 1090: exc({erlang,exit}, [E]) ->
 1091:     erlang:exit(id(E));
 1092: exc({erlang,throw}, [E]) ->
 1093:     erlang:throw(id(E));
 1094: exc({erlang,'++'}, [A,B]) ->
 1095:     erlang:'++'(A, id(B));
 1096: exc({?MODULE,match}, [A,B]) ->
 1097:     match(A, id(B));
 1098: exc({?MODULE,clause}, [A,B]) ->
 1099:     clause(A, id(B));
 1100: exc({?MODULE,id}, [E]) ->
 1101:     id(id(E));
 1102: exc({?MODULE,undef}, [E]) ->
 1103:     undef(id(E));
 1104: exc({?MODULE,lists_reverse}, [A,B]) ->
 1105:     lists_reverse(A, id(B));
 1106: exc(Func, [A,B]) when is_function(Func, 2) ->
 1107:     Func(A, id(B)).
 1108: 
 1109: x_exc(ExcOpts, {erlang,apply}=Func0, [{_,_}=Func,Args]=Args0) ->
 1110:     ?line expect({ctt,{?MODULE,exc},[Func0,Args0]}),
 1111:     ?line x_exc_body(ExcOpts, Func, Args, true);
 1112: x_exc(ExcOpts, {erlang,apply}=Func0, [Func,Args]=Args0) 
 1113:   when is_function(Func, 2)->
 1114:     ?line expect({ctt,{?MODULE,exc},[Func0,Args0]}),
 1115:     ?line x_exc_func(ExcOpts, Func, Args, Args);
 1116: x_exc(ExcOpts, {_,_}=Func, Args) ->
 1117:     ?line expect({ctt,{?MODULE,exc},[Func,Args]}),
 1118:     ?line x_exc_body(ExcOpts, Func, Args, false);
 1119: x_exc(ExcOpts, Func0, [_,Args]=Args0)
 1120:   when is_function(Func0, 2) ->
 1121:     ?line expect({ctt,{?MODULE,exc},[Func0,Args0]}),
 1122:     ?line x_exc_func(ExcOpts, Func0, Args0, Args).
 1123: 
 1124: x_exc_func(ExcOpts, Func, [Func1,Args1]=Args, Id) ->
 1125:     %% Assumes the called fun =:= fun exc/2,
 1126:     %% will utterly fail otherwise.
 1127:     ?line Rtt = not ExcOpts#exc_opts.meta,
 1128:     ?line {module,M} = erlang:fun_info(Func, module),
 1129:     ?line {name,F} = erlang:fun_info(Func, name),
 1130:     ?line expect([{ctt,{?MODULE,id},[Id]},
 1131: 		  ?LINE,{rft,{?MODULE,id,1},Id},
 1132: 		  ?LINE,Rtt,{rtt,{?MODULE,exc,2}},
 1133: 		  ?LINE,{ctt,{M,F},Args}]),
 1134:     ?line case x_exc(ExcOpts, Func1, Args1) of
 1135: 	      {value,Value}=Result ->
 1136: 		  ?line expect([{rft,{M,F,2},Value},
 1137: 				?LINE,{rft,{?MODULE,exc,2},Value}]),
 1138: 		  ?line Result;
 1139: 	      CR ->
 1140: 		  ?line expect([{eft,{M,F,2},CR},
 1141: 				?LINE,{eft,{?MODULE,exc,2},CR}]),
 1142: 		  ?line CR
 1143: 	  end.
 1144: 
 1145: x_exc_body(ExcOpts, {M,F}=Func, Args, Apply) ->
 1146:     ?line Nocatch = ExcOpts#exc_opts.nocatch,
 1147:     ?line Rtt = not ExcOpts#exc_opts.meta,
 1148:     ?line Id = case Apply of
 1149: 		   true  -> Args;
 1150: 		   false -> lists:last(Args)
 1151: 	       end,
 1152:     ?line expect([{ctt,{?MODULE,id},[Id]},
 1153: 		  ?LINE,{rft,{?MODULE,id,1},Id},
 1154: 		  ?LINE,Rtt,{rtt,{?MODULE,exc,2}},
 1155: 		  ?LINE,{ctt,{M,F},Args}]),
 1156:     ?line Arity = length(Args),
 1157:     ?line try exc(Func, Args) of
 1158: 	      Value ->
 1159: 		  ?line x_exc_value(Rtt, M, F, Args, Arity, Value),
 1160: 		  ?line case expect() of
 1161: 			    {rtt,{M,F,Arity}} when Rtt, Apply ->
 1162: 				%% We may get the above when
 1163: 				%% applying a BIF.
 1164: 				?line expect({rft,{?MODULE,exc,2},Value});
 1165: 			    {rtt,{?MODULE,exc,2}} when Rtt, not Apply ->
 1166: 				%% We may get the above when
 1167: 				%% calling a BIF.
 1168: 				?line expect({rft,{?MODULE,exc,2},Value});
 1169: 			    {rft,{?MODULE,exc,2},Value} ->
 1170: 				?line ok
 1171: 			end,
 1172: 		  ?line {value,Value}
 1173: 	  catch
 1174: 	      Thrown when Nocatch ->
 1175: 		  ?line CR = {error,{nocatch,Thrown}},
 1176: 		  ?line x_exc_exception(Rtt, M, F, Args, Arity, CR),
 1177: 		  ?line expect({eft,{?MODULE,exc,2},CR}),
 1178: 		  ?line CR;
 1179: 	      Class:Reason ->
 1180: 		  ?line CR = {Class,Reason},
 1181: 		  ?line x_exc_exception(Rtt, M, F, Args, Arity, CR),
 1182: 		  ?line expect({eft,{?MODULE,exc,2},CR}),
 1183: 		  ?line CR
 1184: 	  end.
 1185: 
 1186: x_exc_value(Rtt, ?MODULE, lists_reverse, [La,Lb], 2, R) ->
 1187:     ?line L = lists:reverse(Lb, La),
 1188:     ?line expect([fun ({ctt,{lists,reverse},[L1,L2]}) ->
 1189: 			  ?line same(L, lists:reverse(L2, L1)),
 1190: 			  ?line next;
 1191: 		      (Msg) ->
 1192: 			  ?line same({rft,{lists,reverse,2},R}, Msg),
 1193: 			  ?line same(R, lists:reverse(L, [])),
 1194: 			  ?line done
 1195: 		  end,
 1196: 		  ?LINE,Rtt,{rtt,{?MODULE,lists_reverse,2}},
 1197: 		  ?LINE,{rft,{?MODULE,lists_reverse,2},R}]);
 1198: x_exc_value(_Rtt, M, F, _, Arity, Value) ->
 1199:     ?line expect({rft,{M,F,Arity},Value}).
 1200: 
 1201: x_exc_exception(_Rtt, ?MODULE, lists_reverse, [La,Lb], 2, CR) ->
 1202:     ?line L = lists:reverse(Lb, La),
 1203:     ?line expect([fun ({ctt,{lists,reverse},[L1,L2]}) ->
 1204: 			  ?line same(L, lists:reverse(L2, L1)),
 1205: 			  ?line next;
 1206: 		      (Msg) ->
 1207: 			  ?line same({eft,{lists,reverse,2},CR}, Msg),
 1208: 			  ?line done
 1209: 		  end,
 1210: 		  ?LINE,{eft,{?MODULE,lists_reverse,2},CR}]);
 1211: x_exc_exception(Rtt, ?MODULE, undef, [_], 1, {Class,Reason}=CR) ->
 1212:     ?line expect([{ctt,{erlang,Class},[Reason]},
 1213: 		  ?LINE,{eft,{erlang,Class,1},CR},
 1214: 		  ?LINE,Rtt,{rtt,{error_handler,crash,1}},
 1215: 		  ?LINE,{eft,{?MODULE,undef,1},CR}]);
 1216: x_exc_exception(_Rtt, M, F, _, Arity, CR) ->
 1217:     ?line expect({eft,{M,F,Arity},CR}).
 1218: 
 1219: x_exc_stacktrace() ->
 1220:     x_exc_stacktrace(erlang:get_stacktrace()).
 1221: %% Truncate stacktrace to below exc/2
 1222: x_exc_stacktrace([{?MODULE,x_exc,4,_}|_]) -> [];
 1223: x_exc_stacktrace([{?MODULE,x_exc_func,4,_}|_]) -> [];
 1224: x_exc_stacktrace([{?MODULE,x_exc_body,4,_}|_]) -> [];
 1225: x_exc_stacktrace([{?MODULE,exc,2,_}|_]) -> [];
 1226: x_exc_stacktrace([H|T]) ->
 1227:     [H|x_exc_stacktrace(T)].
 1228: 
 1229: 
 1230: 
 1231: match(A, B) ->
 1232:     A = B.
 1233: 
 1234: clause(A, A) ->
 1235:     A.
 1236: 
 1237: id(Id) ->
 1238:     Id.
 1239: 
 1240: undef(X) ->
 1241:     ?MODULE:undef(X, X). % undef
 1242: 
 1243: lists_reverse(A, B) ->
 1244:     lists:reverse(A, B).
 1245: 
 1246: 
 1247: 
 1248: %%% Tracee (slave) handling %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 1249: %%%
 1250: 
 1251: slave(Dest, Sync) ->
 1252:     Dest ! Sync,
 1253:     receive
 1254: 	{From,Tag,{apply,M,F,A}} when is_pid(From) ->
 1255: 	    ?line ?dbgformat("Apply: ~p:~p/~p (~p)~n",[M,F,length(A),A]),
 1256: 	    ?line Res = apply(M,F,A),
 1257: 	    ?line ?dbgformat("done Apply: ~p:~p/~p (~p)~n",[M,F,length(A),A]),
 1258: 	    From ! {Tag,Res},
 1259: 	    slave(From, Tag);
 1260: 	{From,Tag,{lambda,Fun}} when is_pid(From) ->
 1261: 	    Res = Fun(),
 1262: 	    From ! {Tag,Res},
 1263: 	    slave(From, Tag);
 1264: 	{From,Tag,{exc_top,Catch,Func,Args}} when is_pid(From) ->
 1265: 	    ?line ?dbgformat("Exc: ~p ~p~p ~n",[Catch,Func,Args]),
 1266: 	    ?line Res = exc_top(Catch, Func, Args),
 1267: 	    ?line ?dbgformat("done Exc: ~p ~p~p ~n",[Catch,Func,Args]),
 1268: 	    From ! {Tag,Res},
 1269: 	    slave(From,Tag);
 1270: 	die ->
 1271: 	    exit(normal)
 1272:     end.
 1273: 
 1274: setup(ProcFlags) ->
 1275:     trace_off(),
 1276:     flush(100),
 1277:     Self = self(),
 1278:     Sync = make_ref(),
 1279:     Pid = spawn(fun () -> slave(Self, Sync) end),
 1280:     Mref = erlang:monitor(process, Pid),
 1281:     receive 
 1282: 	Sync ->
 1283: 	    put(slave, {Pid,Mref}),
 1284: 	    case ProcFlags of
 1285: 		[] -> ok;
 1286: 		_ ->
 1287: 		    erlang:trace(Pid, true, ProcFlags)
 1288: 	    end,
 1289: 	    Pid
 1290:     end.
 1291: 
 1292: shutdown() ->
 1293:     trace_off(),
 1294:     {Pid,Mref} = get(slave),
 1295:     try erlang:is_process_alive(Pid) of
 1296: 	true ->
 1297: 	    Pid ! die,
 1298: 	    receive
 1299: 		{'DOWN',Mref,process,Pid,Reason} ->
 1300: 		    Reason
 1301: 	    end;
 1302: 	_ ->
 1303: 	    not_alive
 1304:     catch _:_ ->
 1305: 	    undefined
 1306:     end.
 1307: 
 1308: trace_off() ->
 1309:     erlang:trace_pattern({'_','_','_'},false,[]),
 1310:     erlang:trace_pattern({'_','_','_'},false,[local]),
 1311:     erlang:trace_pattern({'_','_','_'},false,[meta]),
 1312:     erlang:trace(all, false, [all]).
 1313:     
 1314: 
 1315: apply_slave_async(M,F,A) ->
 1316:     {Pid,Mref} = get(slave),
 1317:     spawn(?MODULE,apply_slave_async,[M,F,A,Pid,Mref]),
 1318:     Pid.
 1319: 
 1320: apply_slave_async(M,F,A,Pid,Mref) ->
 1321:     Tag = make_ref(),
 1322:     Pid ! {self(),Tag,{apply,M,F,A}},
 1323:     result(Tag, Mref).
 1324: 
 1325: apply_slave(M,F,A) ->
 1326:     request({apply,M,F,A}).
 1327: 
 1328: lambda_slave(Fun) ->
 1329:     request({lambda,Fun}).
 1330: 
 1331: exc_slave(Opts, Func, Args) ->
 1332:     try request({exc_top,Opts,Func,Args})
 1333:     catch
 1334: 	Reason ->
 1335: 	    {crash,Reason}
 1336:     end.
 1337: 
 1338: request(Request) ->
 1339:     Tag = make_ref(),
 1340:     {Pid,Mref} = get(slave),
 1341:     Pid ! {self(),Tag,Request},
 1342:     result(Tag, Mref).
 1343: 
 1344: result(Tag, Mref) ->
 1345:     receive
 1346: 	{Tag,Result} ->
 1347: 	    receive
 1348: 		Tag ->
 1349: 		    Result
 1350: 	    end;
 1351: 	{'DOWN',Mref,process,_Pid,Reason} ->
 1352: 	    throw(Reason)
 1353:     end.
 1354: 
 1355: 
 1356: 
 1357: %%% Some receive helpers %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 1358: %%%
 1359: 
 1360: receive_next() ->
 1361:     receive_next(?DEFAULT_RECEIVE_TIMEOUT).
 1362: 
 1363: receive_next(TO) ->
 1364:     receive
 1365: 	M ->
 1366: 	    M
 1367:     after TO ->
 1368: 	    ?t:fail(timeout)
 1369:     end.
 1370: 
 1371: receive_no_next(TO) ->
 1372:     receive M ->
 1373: 	    ?t:fail({unexpected_message,[M|flush(TO)]})
 1374:     after TO ->
 1375: 	    ok
 1376:     end.
 1377: 
 1378: flush(T) ->
 1379:     receive
 1380: 	M ->
 1381: 	    [M|flush(T)]
 1382:     after T ->
 1383: 	    []
 1384:     end.
 1385: 
 1386: 
 1387: 
 1388: %%% Helpers %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 1389: %%%
 1390: 
 1391: %% Do not build garbage
 1392: %%
 1393: seq(M, N, R) when M =< N ->
 1394:     seq(M, N-1, [N|R]);
 1395: seq(_, _, R) -> R.
 1396: 
 1397: %% Do not call traced lists:reverse
 1398: reverse(L) ->
 1399:     reverse(L, []).
 1400: %%
 1401: reverse([], R) -> R;
 1402: reverse([H|T], R) ->
 1403:     reverse(T, [H|R]).
 1404: 
 1405: %% Abbreviate large complex terms to avoid croaking printout
 1406: %%
 1407: abbr(Term) ->
 1408:     abbr(Term, 20).
 1409: %%
 1410: abbr(Tuple, N) when is_tuple(Tuple) ->
 1411:     list_to_tuple(abbr_tuple(Tuple, N, 1));
 1412: abbr(List, N) when is_list(List) ->
 1413:     abbr_list(List, N, []);
 1414: abbr(Term, _) -> Term.
 1415: %%
 1416: abbr_tuple(Tuple, N, J) when J =< size(Tuple) ->
 1417:     if J > N; N =< 0 ->
 1418: 	    ['...'];
 1419:        true ->
 1420: 	    [abbr(element(J, Tuple), N-1)|abbr_tuple(Tuple, J+1, N)]
 1421:     end;
 1422: abbr_tuple(_, _, _) ->
 1423:     [].
 1424: %%
 1425: abbr_list(_, 0, R) ->
 1426:     case io_lib:printable_list(R) of
 1427: 	true ->
 1428: 	    reverse(R, "...");
 1429: 	false ->
 1430: 	    reverse(R, '...')
 1431:     end;
 1432: abbr_list([H|T], N, R) ->
 1433:     M = N-1,
 1434:     abbr_list(T, M, [abbr(H, M)|R]);
 1435: abbr_list(T, _, R) ->
 1436:     reverse(R, T).