opd_trans.c revision 10e23eebca4175a8dfe3a788b2bebacb1fcfce54
137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang/** 22da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * @file daemon/opd_trans.c 32da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Processing the sample buffer 437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * @remark Copyright 2002 OProfile authors 637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * @remark Read the file COPYING 72da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * 82da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * @author John Levon 937fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * @author Philippe Elie 1037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * Modified by Aravind Menon for Xen 1137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * These modifications are: 1237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * Copyright (C) 2005 Hewlett-Packard Co. 1337fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 1437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * Modified by Maynard Johnson <maynardj@us.ibm.com> 1537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * These modifications are: 162da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * (C) Copyright IBM Corporation 2007 172da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang */ 182da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang 192da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang#include "opd_trans.h" 2037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include "opd_kernel.h" 2137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include "opd_sfile.h" 2237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include "opd_anon.h" 2337fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include "opd_stats.h" 2437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include "opd_printf.h" 2537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include "opd_interface.h" 2637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang 2737fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include <limits.h> 2837fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include <string.h> 2937fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include <stdlib.h> 3037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include <stdint.h> 3137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include <stdio.h> 3237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang#include <errno.h> 337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangextern size_t kernel_pointer_size; 357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang 377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangvoid clear_trans_last(struct transient * trans) 387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->last = NULL; 407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->last_anon = NULL; 417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangvoid clear_trans_current(struct transient * trans) 457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->current = NULL; 477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->anon = NULL; 487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wanguint64_t pop_buffer_value(struct transient * trans) 527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang uint64_t val; 547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (!trans->remaining) { 567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang fprintf(stderr, "BUG: popping empty buffer !\n"); 577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang abort(); 587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (kernel_pointer_size == 4) { 617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang uint32_t const * lbuf = (void const *)trans->buffer; 627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang val = *lbuf; 637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } else { 647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang uint64_t const * lbuf = (void const *)trans->buffer; 657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang val = *lbuf; 667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->remaining--; 697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->buffer += kernel_pointer_size; 707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return val; 717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint enough_remaining(struct transient * trans, size_t size) 757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (trans->remaining >= size) 777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 1; 787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(vmisc, "Dangling ESCAPE_CODE.\n"); 807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang opd_stats[OPD_DANGLING_CODE]++; 817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void opd_put_sample(struct transient * trans, unsigned long long pc) 867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang unsigned long long event; 887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (!enough_remaining(trans, 1)) { 907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->remaining = 0; 917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang event = pop_buffer_value(trans); 957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (trans->tracing != TRACING_ON) 977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->event = event; 987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->pc = pc; 1007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* sfile can change at each sample for kernel */ 1027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (trans->in_kernel != 0) 1037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang clear_trans_current(trans); 1047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (!trans->in_kernel && trans->cookie == NO_COOKIE) 1067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->anon = find_anon_mapping(trans); 1077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* get the current sfile if needed */ 1097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (!trans->current) 1107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->current = sfile_find(trans); 1117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* 1137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * can happen if kernel sample falls through the cracks, or if 1147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * it's a sample from an anon region we couldn't find 1157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 1167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (!trans->current) 1177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto out; 1187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* FIXME: this logic is perhaps too harsh? */ 1207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (trans->current->ignored || (trans->last && trans->last->ignored)) 1217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto out; 1227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* log the sample or arc */ 1247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang sfile_log_sample(trans); 1257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangout: 1277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* switch to trace mode */ 1287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (trans->tracing == TRACING_START) 1297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->tracing = TRACING_ON; 1307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang update_trans_last(trans); 1327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void code_unknown(struct transient * trans __attribute__((unused))) 1367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 1377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang fprintf(stderr, "Unknown code !\n"); 1387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang abort(); 1397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void code_ctx_switch(struct transient * trans) 1437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 1447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang clear_trans_current(trans); 1457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (!enough_remaining(trans, 5)) { 1477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->remaining = 0; 1487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 1497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->tid = pop_buffer_value(trans); 1527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->app_cookie = pop_buffer_value(trans); 1537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* must be ESCAPE_CODE, CTX_TGID_CODE, tgid. Like this 1547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * because tgid was added later in a compatible manner. 1557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 1567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang pop_buffer_value(trans); 1577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang pop_buffer_value(trans); 1587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->tgid = pop_buffer_value(trans); 1597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (vmisc) { 1617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang char const * app = find_cookie(trans->app_cookie); 1627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang printf("CTX_SWITCH to tid %lu, tgid %lu, cookie %llx(%s)\n", 1637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (unsigned long)trans->tid, (unsigned long)trans->tgid, 1647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->app_cookie, app ? app : "none"); 1657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void code_cpu_switch(struct transient * trans) 1707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 1717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang clear_trans_current(trans); 1727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (!enough_remaining(trans, 1)) { 1747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->remaining = 0; 1757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 1767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->cpu = pop_buffer_value(trans); 1797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(vmisc, "CPU_SWITCH to %lu\n", trans->cpu); 1807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void code_cookie_switch(struct transient * trans) 1847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 1857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang clear_trans_current(trans); 1867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (!enough_remaining(trans, 1)) { 1887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->remaining = 0; 1897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 190ea4d754fcb81fced7bd1f33ad67f7b50d5fbb291Marco Nelissen } 1917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->cookie = pop_buffer_value(trans); 1937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (vmisc) { 1957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang char const * name = verbose_cookie(trans->cookie); 1967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(vmisc, "COOKIE_SWITCH to cookie %s(%llx)\n", 1977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang name, trans->cookie); 1987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void code_kernel_enter(struct transient * trans) 2037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 2047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(vmisc, "KERNEL_ENTER_SWITCH to kernel\n"); 2057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->in_kernel = 1; 2067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang clear_trans_current(trans); 2077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* subtlety: we must keep trans->cookie cached, 2087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * even though it's meaningless for the kernel - 2097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * we won't necessarily get a cookie switch on 2107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * kernel exit. See comments in opd_sfile.c 2117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 2127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void code_user_enter(struct transient * trans) 2167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 217d52f6d76f66e2e419bd18cc09395a0008edd649cBruce Beare verbprintf(vmisc, "USER_ENTER_SWITCH to user-space\n"); 2187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->in_kernel = 0; 2197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang clear_trans_current(trans); 220ea4d754fcb81fced7bd1f33ad67f7b50d5fbb291Marco Nelissen clear_trans_last(trans); 221ea4d754fcb81fced7bd1f33ad67f7b50d5fbb291Marco Nelissen} 2227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void code_module_loaded(struct transient * trans __attribute__((unused))) 2257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 2267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(vmodule, "MODULE_LOADED_CODE\n"); 2277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang opd_reread_module_info(); 2287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang clear_trans_current(trans); 229b46673f19ebfff0984b7cbc69554239992ea21bbDouglas Leung clear_trans_last(trans); 230b46673f19ebfff0984b7cbc69554239992ea21bbDouglas Leung} 2317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* 2347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * This also implicitly signals the end of the previous 2357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * trace, so we never explicitly set TRACING_OFF when 2367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * processing a buffer. 2377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 2387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void code_trace_begin(struct transient * trans) 2397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 2407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(varcs, "TRACE_BEGIN\n"); 2417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->tracing = TRACING_START; 2427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void code_xen_enter(struct transient * trans) 2457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 2467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(vmisc, "XEN_ENTER_SWITCH to xen\n"); 2477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->in_kernel = 1; 2487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang trans->current = NULL; 2497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* subtlety: we must keep trans->cookie cached, even though it's 2507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * meaningless for Xen - we won't necessarily get a cookie switch 2517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * on Xen exit. See comments in opd_sfile.c. It seems that we can 2527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * get away with in_kernel = 1 as long as we supply the correct 2537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * Xen image, and its address range in startup find_kernel_image 2547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * is modified to look in the Xen image also 2557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 2567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangextern void code_spu_profiling(struct transient * trans); 2597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangextern void code_spu_ctx_switch(struct transient * trans); 2607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wanghandler_t handlers[LAST_CODE + 1] = { 2627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_unknown, 2637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_ctx_switch, 2647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_cpu_switch, 2657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_cookie_switch, 2667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_kernel_enter, 2677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_user_enter, 2687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_module_loaded, 2697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* tgid handled differently */ 2707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_unknown, 2717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_trace_begin, 2727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_unknown, 2737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_xen_enter, 2747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#if defined(__powerpc__) 2757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_spu_profiling, 2767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_spu_ctx_switch, 2777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 2787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang &code_unknown, 2797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}; 2807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangextern void (*special_processor)(struct transient *); 2827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangvoid opd_process_samples(char const * buffer, size_t count) 2847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 2857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang struct transient trans = { 2867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .buffer = buffer, 2877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .remaining = count, 2887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .tracing = TRACING_OFF, 2897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .current = NULL, 2907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .last = NULL, 2917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .cookie = INVALID_COOKIE, 2927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .app_cookie = INVALID_COOKIE, 2937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .anon = NULL, 2947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .last_anon = NULL, 2957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .pc = 0, 2967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .last_pc = 0, 2977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .event = 0, 2987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .in_kernel = -1, 2997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .cpu = -1, 3007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .tid = -1, 3017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .embedded_offset = UNUSED_EMBEDDED_OFFSET, 3027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang .tgid = -1 3037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }; 3047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* FIXME: was uint64_t but it can't compile on alpha where uint64_t 3067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * is an unsigned long and below the printf("..." %llu\n", code) 3077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * generate a warning, this look like a stopper to use c98 types :/ 3087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 3097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang unsigned long long code; 3107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (special_processor) { 3127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang special_processor(&trans); 3137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i; 3177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for (i = 0; i < count && i < 200; i++) { 3197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(vmisc, "buffer[%d] is %x\n", i, buffer[i]); 3207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while (trans.remaining) { 3237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang code = pop_buffer_value(&trans); 3247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(vmisc, "In opd_process_samples (code is %lld)\n", code); 3267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (!is_escape_code(code)) { 3287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang opd_put_sample(&trans, code); 3297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang continue; 3307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (!trans.remaining) { 3337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(vmisc, "Dangling ESCAPE_CODE.\n"); 3347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang opd_stats[OPD_DANGLING_CODE]++; 3357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 3367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // started with ESCAPE_CODE, next is type 3397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang code = pop_buffer_value(&trans); 3407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang verbprintf(vmisc, "next code is %lld\n", code); 3427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (code >= LAST_CODE) { 3437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang fprintf(stderr, "Unknown code %llu\n", code); 3447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang abort(); 3457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang handlers[code](&trans); 3487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 3507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang