/trunk/uspace/app/trace/trace.c |
---|
51,6 → 51,7 |
#include "syscalls.h" |
#include "ipcp.h" |
#include "errors.h" |
#include "trace.h" |
#define THBUF_SIZE 64 |
unsigned thread_hash_buf[THBUF_SIZE]; |
67,7 → 68,11 |
void thread_trace_start(unsigned thread_hash); |
static proto_t *proto_console; |
static task_id_t task_id; |
/** Combination of events/data to print. */ |
display_mask_t display_mask; |
static int task_connect(task_id_t task_id) |
{ |
int rc; |
286,9 → 291,11 |
return; |
} |
/* Print syscall name, id and arguments */ |
printf("%s", syscall_desc[sc_id].name); |
print_sc_args(sc_args, syscall_desc[sc_id].n_args); |
if ((display_mask & DM_SYSCALL) != 0) { |
/* Print syscall name and arguments */ |
printf("%s", syscall_desc[sc_id].name); |
print_sc_args(sc_args, syscall_desc[sc_id].n_args); |
} |
async_serialize_end(); |
} |
312,8 → 319,11 |
return; |
} |
rv_type = syscall_desc[sc_id].rv_type; |
print_sc_retval(sc_rc, rv_type); |
if ((display_mask & DM_SYSCALL) != 0) { |
/* Print syscall return value */ |
rv_type = syscall_desc[sc_id].rv_type; |
print_sc_retval(sc_rc, rv_type); |
} |
switch (sc_id) { |
case SYS_IPC_CALL_ASYNC_FAST: |
428,8 → 438,6 |
int rc; |
int c; |
printf("Syscall Tracer\n"); |
rc = task_connect(task_id); |
if (rc < 0) { |
printf("Failed to connect to task %lld\n", task_id); |
532,30 → 540,91 |
static void print_syntax() |
{ |
printf("Syntax: trace <task_id>\n"); |
printf("Syntax: trace [+<events>] <task_id>\n"); |
printf("Events: (default is +tp)\n"); |
printf("\n"); |
printf("\tt ... Thread creation and termination\n"); |
printf("\ts ... System calls\n"); |
printf("\ti ... Low-level IPC\n"); |
printf("\tp ... Protocol level\n"); |
printf("\n"); |
printf("Example: trace +tsip 12\n"); |
} |
int main(int argc, char *argv[]) |
static display_mask_t parse_display_mask(char *text) |
{ |
task_id_t task_id; |
display_mask_t dm; |
char *c; |
c = text; |
while (*c) { |
switch (*c) { |
case 't': dm = dm | DM_THREAD; break; |
case 's': dm = dm | DM_SYSCALL; break; |
case 'i': dm = dm | DM_IPC; break; |
case 'p': dm = dm | DM_SYSTEM | DM_USER; break; |
default: |
printf("Unexpected event type '%c'\n", *c); |
exit(1); |
} |
++c; |
} |
return dm; |
} |
static int parse_args(int argc, char *argv[]) |
{ |
char *arg; |
char *err_p; |
if (argc != 2) { |
printf("Mising argument\n"); |
--argc; ++argv; |
while (argc > 1) { |
arg = *argv; |
if (arg[0] == '+') { |
display_mask = parse_display_mask(&arg[1]); |
} else { |
printf("Unexpected argument '%s'\n", arg); |
print_syntax(); |
return -1; |
} |
--argc; ++argv; |
} |
if (argc != 1) { |
printf("Missing argument\n"); |
print_syntax(); |
return 1; |
} |
task_id = strtol(argv[1], &err_p, 10); |
task_id = strtol(*argv, &err_p, 10); |
if (*err_p) { |
printf("Task ID syntax error\n"); |
print_syntax(); |
return 1; |
return -1; |
} |
return 0; |
} |
int main(int argc, char *argv[]) |
{ |
printf("System Call / IPC Tracer\n"); |
display_mask = DM_THREAD | DM_SYSTEM | DM_USER; |
if (parse_args(argc, argv) < 0) |
return 1; |
main_init(); |
trace_active_task(task_id); |
return 0; |
} |
/** @} |
/trunk/uspace/app/trace/trace.h |
---|
0,0 → 1,57 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#ifndef TRACE_H_ |
#define TRACE_H_ |
/** |
* Classes of events that can be displayed. Can be or-ed together. |
*/ |
typedef enum { |
DM_THREAD = 1, /**< Thread creation and termination events */ |
DM_SYSCALL = 2, /**< System calls */ |
DM_IPC = 4, /**< Low-level IPC */ |
DM_SYSTEM = 8, /**< Sysipc protocol */ |
DM_USER = 16 /**< User IPC protocols */ |
} display_mask_t; |
/** Combination of events to print. */ |
extern display_mask_t display_mask; |
#endif |
/** @} |
*/ |
/trunk/uspace/app/trace/ipcp.c |
---|
38,6 → 38,7 |
#include "ipc_desc.h" |
#include "proto.h" |
#include "trace.h" |
#include "ipcp.h" |
#define IPCP_CALLID_SYNC 0 |
177,22 → 178,48 |
pending_call_t *pcall; |
proto_t *proto; |
unsigned long key[1]; |
oper_t *oper; |
if (have_conn[phone]) proto = connections[phone].proto; |
else proto = NULL; |
// printf("ipcp_call_out()\n"); |
printf("call id: 0x%x, phone: %d, proto: %s, method: ", hash, phone, |
(proto ? proto->name : "n/a")); |
ipc_m_print(proto, IPC_GET_METHOD(*call)); |
printf(" args: (%u, %u, %u, %u, %u)\n", |
IPC_GET_ARG1(*call), |
IPC_GET_ARG2(*call), |
IPC_GET_ARG3(*call), |
IPC_GET_ARG4(*call), |
IPC_GET_ARG5(*call) |
); |
if ((display_mask & DM_IPC) != 0) { |
printf("Call ID: 0x%x, phone: %d, proto: %s, method: ", hash, |
phone, (proto ? proto->name : "n/a")); |
ipc_m_print(proto, IPC_GET_METHOD(*call)); |
printf(" args: (%u, %u, %u, %u, %u)\n", |
IPC_GET_ARG1(*call), |
IPC_GET_ARG2(*call), |
IPC_GET_ARG3(*call), |
IPC_GET_ARG4(*call), |
IPC_GET_ARG5(*call) |
); |
} |
if ((display_mask & DM_USER) != 0) { |
if (proto != NULL) { |
oper = proto_get_oper(proto, IPC_GET_METHOD(*call)); |
} else { |
oper = NULL; |
} |
if (oper != NULL) { |
printf("%s(%d).%s", (proto ? proto->name : "n/a"), |
phone, (oper ? oper->name : "unknown")); |
printf("(%u, %u, %u, %u, %u)\n", |
IPC_GET_ARG1(*call), |
IPC_GET_ARG2(*call), |
IPC_GET_ARG3(*call), |
IPC_GET_ARG4(*call), |
IPC_GET_ARG5(*call) |
); |
} |
} |
/* Store call in hash table for response matching */ |
pcall = malloc(sizeof(pending_call_t)); |
205,7 → 232,8 |
hash_table_insert(&pending_calls, key, &pcall->link); |
} |
static void parse_answer(pending_call_t *pcall, ipc_call_t *answer) |
static void parse_answer(ipc_callid_t hash, pending_call_t *pcall, |
ipc_call_t *answer) |
{ |
int phone; |
ipcarg_t method; |
219,9 → 247,18 |
phone = pcall->phone_hash; |
method = IPC_GET_METHOD(pcall->question); |
retval = IPC_GET_RETVAL(*answer); |
printf("phone=%d, method=%d, retval=%d\n", |
phone, method, retval); |
if ((display_mask & DM_IPC) != 0) { |
printf("Response to 0x%x: retval=%d, args = (%u, %u, %u, %u, %u)\n", |
hash, retval, IPC_GET_ARG1(*answer), |
IPC_GET_ARG2(*answer), IPC_GET_ARG3(*answer), |
IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer)); |
} |
if ((display_mask & DM_USER) != 0) { |
printf("-> %d\n", retval); |
} |
if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) { |
/* Connected to a service (through NS) */ |
service = IPC_GET_ARG1(pcall->question); |
229,8 → 266,10 |
if (proto == NULL) proto = proto_unknown; |
cphone = IPC_GET_ARG5(*answer); |
printf("registering connection (phone %d, protocol: %s)\n", cphone, |
proto->name); |
if ((display_mask & DM_SYSTEM) != 0) { |
printf("Registering connection (phone %d, protocol: %s)\n", cphone, |
proto->name); |
} |
ipcp_connection_set(cphone, 0, proto); |
} |
} |
254,7 → 293,9 |
if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) { |
/* Not a response */ |
printf("Not a response (hash %d)\n", hash); |
if ((display_mask & DM_IPC) != 0) { |
printf("Not a response (hash %d)\n", hash); |
} |
return; |
} |
263,13 → 304,15 |
item = hash_table_find(&pending_calls, key); |
if (item == NULL) return; // No matching question found |
/* |
* Response matched to question. |
*/ |
pcall = hash_table_get_instance(item, pending_call_t, link); |
printf("response matched to question\n"); |
hash_table_remove(&pending_calls, key, 1); |
parse_answer(pcall, call); |
parse_answer(hash, pcall, call); |
free(pcall); |
} |
281,8 → 324,10 |
void ipcp_hangup(int phone, int rc) |
{ |
printf("hangup phone %d -> %d\n", phone, rc); |
ipcp_connection_clear(phone); |
if ((display_mask & DM_SYSTEM) != 0) { |
printf("Hang phone %d up -> %d\n", phone, rc); |
ipcp_connection_clear(phone); |
} |
} |
/** @} |