~clint-fewbar/ubuntu/precise/erlang/merge-15b

« back to all changes in this revision

Viewing changes to erts/emulator/beam/erl_bif_trace.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2011-05-05 15:48:43 UTC
  • mfrom: (3.5.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110505154843-0om6ekzg6m7ugj27
Tags: 1:14.b.2-dfsg-3ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop libwxgtk2.8-dev build dependency. Wx isn't in main, and not
    supposed to.
  - Drop erlang-wx binary.
  - Drop erlang-wx dependency from -megaco, -common-test, and -reltool, they
    do not really need wx. Also drop it from -debugger; the GUI needs wx,
    but it apparently has CLI bits as well, and is also needed by -megaco,
    so let's keep the package for now.
  - debian/patches/series: Do what I meant, and enable build-options.patch
    instead.
* Additional changes:
  - Drop erlang-wx from -et
* Dropped Changes:
  - patches/pcre-crash.patch: CVE-2008-2371: outer level option with
    alternatives caused crash. (Applied Upstream)
  - fix for ssl certificate verification in newSSL: 
    ssl_cacertfile_fix.patch (Applied Upstream)
  - debian/patches/series: Enable native.patch again, to get stripped beam
    files and reduce the package size again. (build-options is what
    actually accomplished this)
  - Remove build-options.patch on advice from upstream and because it caused
    odd build failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * %CopyrightBegin%
3
 
 * 
4
 
 * Copyright Ericsson AB 1999-2009. All Rights Reserved.
5
 
 * 
 
3
 *
 
4
 * Copyright Ericsson AB 1999-2010. All Rights Reserved.
 
5
 *
6
6
 * The contents of this file are subject to the Erlang Public License,
7
7
 * Version 1.1, (the "License"); you may not use this file except in
8
8
 * compliance with the License. You should have received a copy of the
9
9
 * Erlang Public License along with this software. If not, it can be
10
10
 * retrieved online at http://www.erlang.org/.
11
 
 * 
 
11
 *
12
12
 * Software distributed under the License is distributed on an "AS IS"
13
13
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
14
 * the License for the specific language governing rights and limitations
15
15
 * under the License.
16
 
 * 
 
16
 *
17
17
 * %CopyrightEnd%
18
18
 */
19
19
 
40
40
 
41
41
#define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
42
42
 
43
 
static erts_smp_mtx_t              trace_pattern_mutex;
44
 
const struct trace_pattern_flags   erts_trace_pattern_flags_off = {0, 0, 0, 0};
 
43
const struct trace_pattern_flags   erts_trace_pattern_flags_off = {0, 0, 0, 0, 0};
45
44
static int                         erts_default_trace_pattern_is_on;
46
45
static Binary                     *erts_default_match_spec;
47
46
static Binary                     *erts_default_meta_match_spec;
65
64
void
66
65
erts_bif_trace_init(void)
67
66
{
68
 
    erts_smp_mtx_init(&trace_pattern_mutex, "trace_pattern");
69
67
    erts_default_trace_pattern_is_on = 0;
70
68
    erts_default_match_spec = NULL;
71
69
    erts_default_meta_match_spec = NULL;
86
84
Eterm
87
85
trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)       
88
86
{
89
 
    Eterm mfa[3];
 
87
    DeclareTmpHeap(mfa,3,p); /* Not really heap here, but might be when setting pattern */
90
88
    int i;
91
89
    int matches = 0;
92
90
    int specified = 0;
101
99
    erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
102
100
    erts_smp_block_system(0);
103
101
 
 
102
    UseTmpHeap(3,p);
104
103
    /*
105
104
     * Check and compile the match specification.
106
105
     */
185
184
                flags.breakpoint = 1;
186
185
                flags.call_count = 1;
187
186
                break;
 
187
            case am_call_time:
 
188
                if (is_global) {
 
189
                    goto error;
 
190
                }
 
191
                flags.breakpoint = 1;
 
192
                flags.call_time = 1;
 
193
                break;
 
194
 
188
195
            default:
189
196
                goto error;
190
197
            }
194
201
        goto error;
195
202
    }
196
203
    
197
 
    if (match_prog_set && !flags.local && !flags.meta && flags.call_count) {
198
 
        /* A match prog is not allowed with just call_count */
 
204
    if (match_prog_set && !flags.local && !flags.meta && (flags.call_count || flags.call_time)) {
 
205
        /* A match prog is not allowed with just call_count or call_time*/
199
206
        goto error;
200
207
    }
201
208
 
234
241
                    |= flags.meta;
235
242
                erts_default_trace_pattern_flags.call_count
236
243
                    |= (on == 1) ? flags.call_count : 0;
 
244
                erts_default_trace_pattern_flags.call_time
 
245
                    |= (on == 1) ? flags.call_time : 0;
237
246
            } else {
238
247
                erts_default_trace_pattern_flags.local
239
248
                    &= ~flags.local;
241
250
                    &= ~flags.meta;
242
251
                erts_default_trace_pattern_flags.call_count
243
252
                    &= ~flags.call_count;
 
253
                erts_default_trace_pattern_flags.call_time
 
254
                    &= ~flags.call_time;
244
255
                if (! (erts_default_trace_pattern_flags.breakpoint =
245
256
                       erts_default_trace_pattern_flags.local |
246
257
                       erts_default_trace_pattern_flags.meta |
247
 
                       erts_default_trace_pattern_flags.call_count)) {
 
258
                       erts_default_trace_pattern_flags.call_count |
 
259
                       erts_default_trace_pattern_flags.call_time)) {
248
260
                    erts_default_trace_pattern_is_on = !!on; /* i.e off */
249
261
                }
250
262
            }
266
278
            if (on) {
267
279
                if (on != 1) {
268
280
                    flags.call_count = 0;
 
281
                    flags.call_time  = 0;
269
282
                }
270
 
                flags.breakpoint = flags.local | flags.meta | flags.call_count;
 
283
                flags.breakpoint = flags.local | flags.meta | flags.call_count | flags.call_time;
271
284
                erts_default_trace_pattern_flags = flags; /* Struct copy */
272
285
                erts_default_trace_pattern_is_on = !!flags.breakpoint;
273
286
            }
312
325
    MatchSetUnref(match_prog_set);
313
326
 
314
327
 done:
315
 
 
 
328
    UnUseTmpHeap(3,p);
316
329
    erts_smp_release_system();
317
330
    erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
318
331
 
322
335
 
323
336
    MatchSetUnref(match_prog_set);
324
337
 
 
338
    UnUseTmpHeap(3,p);
325
339
    erts_smp_release_system();
326
340
    erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
327
341
    BIF_ERROR(p, BADARG);
334
348
                               struct trace_pattern_flags *trace_pattern_flags,
335
349
                               Eterm *meta_tracer_pid)
336
350
{
337
 
    erts_smp_mtx_lock(&trace_pattern_mutex);
338
351
    if (trace_pattern_is_on)
339
352
        *trace_pattern_is_on = erts_default_trace_pattern_is_on;
340
353
    if (match_spec)
345
358
        *trace_pattern_flags = erts_default_trace_pattern_flags;
346
359
    if (meta_tracer_pid)
347
360
        *meta_tracer_pid = erts_default_meta_tracer_pid;
348
 
    erts_smp_mtx_unlock(&trace_pattern_mutex);
349
361
}
350
362
 
351
363
 
352
364
 
353
 
 
354
365
Uint 
355
366
erts_trace_flag2bit(Eterm flag) 
356
367
{
378
389
    default: return 0;
379
390
    }
380
391
}
381
 
 
 
392
 
382
393
/* Scan the argument list and sort out the trace flags.
383
394
**
384
395
** Returns !0 on success, 0 on failure.
929
940
#define FUNC_TRACE_LOCAL_TRACE  (1<<2)
930
941
#define FUNC_TRACE_META_TRACE   (1<<3)
931
942
#define FUNC_TRACE_COUNT_TRACE  (1<<4)
 
943
#define FUNC_TRACE_TIME_TRACE   (1<<5)
932
944
/*
933
945
 * Returns either FUNC_TRACE_NOEXIST, FUNC_TRACE_UNTRACED,
934
946
 * FUNC_TRACE_GLOBAL_TRACE, or,
943
955
 *
944
956
 * If the return value contains FUNC_TRACE_COUNT_TRACE, *count is set.
945
957
 */
946
 
static int function_is_traced(Eterm mfa[3], 
947
 
                              Binary **ms, /* out */
948
 
                              Binary **ms_meta,  /* out */
 
958
static int function_is_traced(Process *p,
 
959
                              Eterm mfa[3],
 
960
                              Binary **ms,              /* out */
 
961
                              Binary **ms_meta,         /* out */
949
962
                              Eterm   *tracer_pid_meta, /* out */
950
 
                              Sint    *count)    /* out */
 
963
                              Sint    *count,           /* out */
 
964
                              Eterm   *call_time)       /* out */
951
965
{
952
966
    Export e;
953
967
    Export* ep;
954
968
    int i;
955
 
    Uint *code;
 
969
    BeamInstr *code;
956
970
 
957
971
    /* First look for an export entry */
958
972
    e.code[0] = mfa[0];
960
974
    e.code[2] = mfa[2];
961
975
    if ((ep = export_get(&e)) != NULL) {
962
976
        if (ep->address == ep->code+3 &&
963
 
            ep->code[3] != (Uint) em_call_error_handler) {
964
 
            if (ep->code[3] == (Uint) em_call_traced_function) {
 
977
            ep->code[3] != (BeamInstr) em_call_error_handler) {
 
978
            if (ep->code[3] == (BeamInstr) em_call_traced_function) {
965
979
                *ms = ep->match_prog_set;
966
980
                return FUNC_TRACE_GLOBAL_TRACE;
967
981
            }
968
 
            if (ep->code[3] == (Uint) em_apply_bif) {
 
982
            if (ep->code[3] == (BeamInstr) em_apply_bif) {
969
983
                for (i = 0; i < BIF_SIZE; ++i) {
970
984
                    if (bif_export[i] == ep) {
971
985
                        int r = 0;
978
992
                                r |= FUNC_TRACE_LOCAL_TRACE;
979
993
                                *ms = ep->match_prog_set;
980
994
                            }
981
 
                            if (erts_is_mtrace_bif(ep->code+3, ms_meta, 
 
995
                            if (erts_is_mtrace_break(ep->code+3, ms_meta,
982
996
                                                   tracer_pid_meta)) {
983
997
                                r |= FUNC_TRACE_META_TRACE;
984
998
                            }
 
999
                            if (erts_is_time_break(p, ep->code+3, call_time)) {
 
1000
                                r |= FUNC_TRACE_TIME_TRACE;
 
1001
                            }
985
1002
                        }
986
1003
                        return r ? r : FUNC_TRACE_UNTRACED;
987
1004
                    }
999
1016
            | (erts_is_mtrace_break(code, ms_meta, tracer_pid_meta)
1000
1017
               ? FUNC_TRACE_META_TRACE : 0)
1001
1018
            | (erts_is_count_break(code, count)
1002
 
               ? FUNC_TRACE_COUNT_TRACE : 0);
 
1019
               ? FUNC_TRACE_COUNT_TRACE : 0)
 
1020
            | (erts_is_time_break(p, code, call_time)
 
1021
               ? FUNC_TRACE_TIME_TRACE : 0);
1003
1022
        
1004
1023
        return r ? r : FUNC_TRACE_UNTRACED;
1005
1024
    } 
1011
1030
{
1012
1031
    Eterm* tp;
1013
1032
    Eterm* hp;
1014
 
    Eterm mfa[3];
 
1033
    DeclareTmpHeap(mfa,3,p); /* Not really heap here, but might be when setting pattern */
1015
1034
    Binary *ms = NULL, *ms_meta = NULL;
1016
1035
    Sint count = 0;
1017
1036
    Eterm traced = am_false;
1018
1037
    Eterm match_spec = am_false;
1019
1038
    Eterm retval = am_false;
1020
1039
    Eterm meta = am_false;
 
1040
    Eterm call_time = NIL;
1021
1041
    int r;
1022
1042
 
 
1043
 
 
1044
    UseTmpHeap(3,p);
 
1045
 
1023
1046
    if (!is_tuple(func_spec)) {
1024
1047
        goto error;
1025
1048
    }
1034
1057
    mfa[1] = tp[2];
1035
1058
    mfa[2] = signed_val(tp[3]);
1036
1059
 
1037
 
    r = function_is_traced(mfa, &ms, &ms_meta, &meta, &count);
 
1060
#ifdef ERTS_SMP
 
1061
    if ( (key == am_call_time) || (key == am_all)) {
 
1062
        erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
 
1063
        erts_smp_block_system(0);
 
1064
    }
 
1065
#endif
 
1066
 
 
1067
    r = function_is_traced(p, mfa, &ms, &ms_meta, &meta, &count, &call_time);
 
1068
 
 
1069
#ifdef ERTS_SMP
 
1070
    if ( (key == am_call_time) || (key == am_all)) {
 
1071
        erts_smp_release_system();
 
1072
        erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
 
1073
    }
 
1074
#endif
 
1075
 
1038
1076
    switch (r) {
1039
1077
    case FUNC_TRACE_NOEXIST:
 
1078
        UnUseTmpHeap(3,p);
1040
1079
        hp = HAlloc(p, 3);
1041
1080
        return TUPLE2(hp, key, am_undefined);
1042
1081
    case FUNC_TRACE_UNTRACED:
 
1082
        UnUseTmpHeap(3,p);
1043
1083
        hp = HAlloc(p, 3);
1044
1084
        return TUPLE2(hp, key, am_false);
1045
1085
    case FUNC_TRACE_GLOBAL_TRACE:
1085
1125
                erts_make_integer(count, p);
1086
1126
        }
1087
1127
        break;
 
1128
    case am_call_time:
 
1129
        if (r & FUNC_TRACE_TIME_TRACE) {
 
1130
            retval = call_time;
 
1131
        }
 
1132
        break;
1088
1133
    case am_all: {
1089
 
        Eterm match_spec_meta = am_false, c = am_false, t;
 
1134
        Eterm match_spec_meta = am_false, c = am_false, t, ct = am_false;
1090
1135
        
1091
1136
        if (ms) {
1092
1137
            match_spec = MatchSetGetSource(ms);
1104
1149
                erts_make_integer(-count-1, p) : 
1105
1150
                erts_make_integer(count, p);
1106
1151
        }
1107
 
        hp = HAlloc(p, (3+2)*5);
 
1152
        if (r & FUNC_TRACE_TIME_TRACE) {
 
1153
            ct = call_time;
 
1154
        }
 
1155
        hp = HAlloc(p, (3+2)*6);
1108
1156
        retval = NIL;
1109
1157
        t = TUPLE2(hp, am_call_count, c); hp += 3;
1110
1158
        retval = CONS(hp, t, retval); hp += 2;
 
1159
        t = TUPLE2(hp, am_call_time, ct); hp += 3;
 
1160
        retval = CONS(hp, t, retval); hp += 2;
1111
1161
        t = TUPLE2(hp, am_meta_match_spec, match_spec_meta); hp += 3;
1112
1162
        retval = CONS(hp, t, retval); hp += 2;
1113
1163
        t = TUPLE2(hp, am_meta, meta); hp += 3;
1120
1170
    default:
1121
1171
        goto error;
1122
1172
    }
 
1173
    UnUseTmpHeap(3,p);
1123
1174
    hp = HAlloc(p, 3);
1124
1175
    return TUPLE2(hp, key, retval);
1125
1176
 
1126
1177
 error:
 
1178
    UnUseTmpHeap(3,p);
1127
1179
    BIF_ERROR(p, BADARG);
1128
1180
}
1129
1181
 
1201
1253
        } else {
1202
1254
            return TUPLE2(hp, key, am_false);
1203
1255
        }
 
1256
    case am_call_time:
 
1257
        hp = HAlloc(p, 3);
 
1258
        if (erts_default_trace_pattern_flags.call_time) {
 
1259
            return TUPLE2(hp, key, am_true);
 
1260
        } else {
 
1261
            return TUPLE2(hp, key, am_false);
 
1262
        }
1204
1263
    case am_all:
1205
1264
        {
1206
1265
            Eterm match_spec = am_false, meta_match_spec = am_false, r = NIL, t;
1275
1334
        for (j = 0; j < specified && mfa[j] == ep->code[j]; j++) {
1276
1335
            /* Empty loop body */
1277
1336
        }
 
1337
 
1278
1338
        if (j == specified) {
1279
1339
            if (on) {
1280
1340
                if (! flags.breakpoint)
1312
1372
                    if (erts_bif_trace_flags[i] & BIF_TRACE_AS_META) {
1313
1373
                        ASSERT(ExportIsBuiltIn(bif_export[i]));
1314
1374
                        erts_clear_mtrace_bif
1315
 
                            ((Uint *)bif_export[i]->code + 3);
 
1375
                            ((BeamInstr *)bif_export[i]->code + 3);
1316
1376
                        erts_bif_trace_flags[i] &= ~BIF_TRACE_AS_META;
1317
1377
                    }
1318
1378
                    set_trace_bif(i, match_prog_set);
1341
1401
                    }
1342
1402
                    if (flags.meta) {
1343
1403
                        erts_set_mtrace_bif
1344
 
                            ((Uint *)bif_export[i]->code + 3,
 
1404
                            ((BeamInstr *)bif_export[i]->code + 3,
1345
1405
                             meta_match_prog_set, meta_tracer_pid);
1346
1406
                        erts_bif_trace_flags[i] |= BIF_TRACE_AS_META;
1347
1407
                        erts_bif_trace_flags[i] &= ~BIF_TRACE_AS_GLOBAL;
1348
1408
                        m = 1;
1349
1409
                    }
 
1410
                    if (flags.call_time) {
 
1411
                        erts_set_time_trace_bif(bif_export[i]->code + 3, on);
 
1412
                        /* I don't want to remove any other tracers */
 
1413
                        erts_bif_trace_flags[i] |= BIF_TRACE_AS_CALL_TIME;
 
1414
                        m = 1;
 
1415
                    }
1350
1416
                    if (erts_bif_trace_flags[i]) {
1351
1417
                        setup_bif_trace(i);
1352
1418
                    }
1361
1427
                    if (flags.meta) {
1362
1428
                        if (erts_bif_trace_flags[i] & BIF_TRACE_AS_META) {
1363
1429
                            erts_clear_mtrace_bif
1364
 
                                ((Uint *)bif_export[i]->code + 3);
 
1430
                                ((BeamInstr *)bif_export[i]->code + 3);
1365
1431
                            erts_bif_trace_flags[i] &= ~BIF_TRACE_AS_META;
1366
1432
                        }
1367
1433
                        m = 1;
1368
1434
                    }
 
1435
                    if (flags.call_time) {
 
1436
                        erts_clear_time_trace_bif(bif_export[i]->code + 3);
 
1437
                        erts_bif_trace_flags[i] &= ~BIF_TRACE_AS_CALL_TIME;
 
1438
                        m = 1;
 
1439
                    }
1369
1440
                    if (! erts_bif_trace_flags[i]) {
1370
1441
                        reset_bif_trace(i);
1371
1442
                    }
1383
1454
            erts_clear_trace_break(mfa, specified);
1384
1455
            erts_clear_mtrace_break(mfa, specified);
1385
1456
            erts_clear_count_break(mfa, specified);
 
1457
            erts_clear_time_break(mfa, specified);
1386
1458
        } else {
1387
1459
            int m = 0;
1388
1460
            if (flags.local) {
1396
1468
            if (flags.call_count) {
1397
1469
                m = erts_set_count_break(mfa, specified, on);
1398
1470
            }
 
1471
            if (flags.call_time) {
 
1472
                m = erts_set_time_break(mfa, specified, on);
 
1473
            }
1399
1474
            /* All assignments to 'm' above should give the same value,
1400
1475
             * so just use the last */
1401
1476
            matches += m;
1411
1486
        if (flags.call_count) {
1412
1487
            m = erts_clear_count_break(mfa, specified);
1413
1488
        }
 
1489
        if (flags.call_time) {
 
1490
            m = erts_clear_time_break(mfa, specified);
 
1491
        }
1414
1492
        /* All assignments to 'm' above should give the same value,
1415
1493
         * so just use the last */
1416
1494
        matches += m;
1430
1508
setup_func_trace(Export* ep, void* match_prog)
1431
1509
{
1432
1510
    if (ep->address == ep->code+3) {
1433
 
        if (ep->code[3] == (Uint) em_call_error_handler) {
 
1511
        if (ep->code[3] == (BeamInstr) em_call_error_handler) {
1434
1512
            return 0;
1435
 
        } else if (ep->code[3] == (Uint) em_call_traced_function) {
 
1513
        } else if (ep->code[3] == (BeamInstr) em_call_traced_function) {
1436
1514
            MatchSetUnref(ep->match_prog_set);
1437
1515
            ep->match_prog_set = match_prog;
1438
1516
            MatchSetRef(ep->match_prog_set);
1452
1530
        return 0;
1453
1531
    }
1454
1532
    
1455
 
    ep->code[3] = (Uint) em_call_traced_function;
1456
 
    ep->code[4] = (Uint) ep->address;
 
1533
    ep->code[3] = (BeamInstr) em_call_traced_function;
 
1534
    ep->code[4] = (BeamInstr) ep->address;
1457
1535
    ep->address = ep->code+3;
1458
1536
    ep->match_prog_set = match_prog;
1459
1537
    MatchSetRef(ep->match_prog_set);
1465
1543
    
1466
1544
    ASSERT(ExportIsBuiltIn(ep));
1467
1545
    ASSERT(ep->code[4]);
1468
 
    ep->code[4] = (Uint) bif_table[bif_index].traced;
 
1546
    ep->code[4] = (BeamInstr) bif_table[bif_index].traced;
1469
1547
}
1470
1548
 
1471
1549
static void set_trace_bif(int bif_index, void* match_prog) {
1492
1570
reset_func_trace(Export* ep)
1493
1571
{
1494
1572
    if (ep->address == ep->code+3) {
1495
 
        if (ep->code[3] == (Uint) em_call_error_handler) {
 
1573
        if (ep->code[3] == (BeamInstr) em_call_error_handler) {
1496
1574
            return 0;
1497
 
        } else if (ep->code[3] == (Uint) em_call_traced_function) {
 
1575
        } else if (ep->code[3] == (BeamInstr) em_call_traced_function) {
1498
1576
            ep->address = (Uint *) ep->code[4];
1499
1577
            MatchSetUnref(ep->match_prog_set);
1500
1578
            ep->match_prog_set = NULL;
1527
1605
    ASSERT(ExportIsBuiltIn(ep));
1528
1606
    ASSERT(ep->code[4]);
1529
1607
    ASSERT(! ep->match_prog_set);
1530
 
    ASSERT(! erts_is_mtrace_bif((Uint *)ep->code+3, NULL, NULL));
1531
 
    ep->code[4] = (Uint) bif_table[bif_index].f;
 
1608
    ASSERT(! erts_is_mtrace_break((BeamInstr *)ep->code+3, NULL, NULL));
 
1609
    ep->code[4] = (BeamInstr) bif_table[bif_index].f;
1532
1610
}
1533
1611
 
1534
1612
static void clear_trace_bif(int bif_index) {
2083
2161
#ifdef ERTS_SMP
2084
2162
    bp = new_message_buffer(REF_THING_SIZE + 4);
2085
2163
    hp = &bp->mem[0];
2086
 
    msg_ref = STORE_NC(&hp, &bp->off_heap.externals, ref);
 
2164
    msg_ref = STORE_NC(&hp, &bp->off_heap, ref);
2087
2165
#else
2088
2166
    hp = HAlloc(BIF_P, 4);
2089
2167
    msg_ref = ref;