1 /***************************************************************************
2 * Copyright (C) 2005, 2007 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
24 #include <helper/log.h>
28 int trace_point(struct target
*target
, uint32_t number
)
30 struct trace
*trace
= target
->trace_info
;
32 LOG_DEBUG("tracepoint: %i", (int)number
);
34 if (number
< trace
->num_trace_points
)
35 trace
->trace_points
[number
].hit_counter
++;
37 if (trace
->trace_history_size
)
39 trace
->trace_history
[trace
->trace_history_pos
++] = number
;
40 if (trace
->trace_history_pos
== trace
->trace_history_size
)
42 trace
->trace_history_pos
= 0;
43 trace
->trace_history_overflowed
= 1;
50 COMMAND_HANDLER(handle_trace_point_command
)
52 struct target
*target
= get_current_target(CMD_CTX
);
53 struct trace
*trace
= target
->trace_info
;
59 for (i
= 0; i
< trace
->num_trace_points
; i
++)
61 command_print(CMD_CTX
, "trace point 0x%8.8" PRIx32
" (%lld times hit)",
62 trace
->trace_points
[i
].address
,
63 (long long)trace
->trace_points
[i
].hit_counter
);
69 if (!strcmp(CMD_ARGV
[0], "clear"))
71 if (trace
->trace_points
)
73 free(trace
->trace_points
);
74 trace
->trace_points
= NULL
;
76 trace
->num_trace_points
= 0;
77 trace
->trace_points_size
= 0;
82 /* resize array if necessary */
83 if (!trace
->trace_points
|| (trace
->trace_points_size
== trace
->num_trace_points
))
85 trace
->trace_points
= realloc(trace
->trace_points
, sizeof(struct trace_point
) * (trace
->trace_points_size
+ 32));
86 trace
->trace_points_size
+= 32;
90 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
91 trace
->trace_points
[trace
->num_trace_points
].address
= address
;
92 trace
->trace_points
[trace
->num_trace_points
].hit_counter
= 0;
93 trace
->num_trace_points
++;
98 COMMAND_HANDLER(handle_trace_history_command
)
100 struct target
*target
= get_current_target(CMD_CTX
);
101 struct trace
*trace
= target
->trace_info
;
105 trace
->trace_history_pos
= 0;
106 trace
->trace_history_overflowed
= 0;
108 if (!strcmp(CMD_ARGV
[0], "clear"))
110 /* clearing is implicit, we've just reset position anyway */
114 if (trace
->trace_history
)
115 free(trace
->trace_history
);
117 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], trace
->trace_history_size
);
118 trace
->trace_history
= malloc(sizeof(uint32_t) * trace
->trace_history_size
);
120 command_print(CMD_CTX
, "new trace history size: %i", (int)(trace
->trace_history_size
));
126 uint32_t last
= trace
->trace_history_pos
;
128 if (!trace
->trace_history_size
) {
129 command_print(CMD_CTX
, "trace history buffer is not allocated");
132 if (trace
->trace_history_overflowed
)
134 first
= trace
->trace_history_pos
;
135 last
= trace
->trace_history_pos
- 1;
138 for (i
= first
; (i
% trace
->trace_history_size
) != last
; i
++)
140 if (trace
->trace_history
[i
% trace
->trace_history_size
] < trace
->num_trace_points
)
143 address
= trace
->trace_points
[trace
->trace_history
[i
% trace
->trace_history_size
]].address
;
144 command_print(CMD_CTX
, "trace point %i: 0x%8.8" PRIx32
"",
145 (int)(trace
->trace_history
[i
% trace
->trace_history_size
]),
151 command_print(CMD_CTX
, "trace point %i: -not defined-", (int)(trace
->trace_history
[i
% trace
->trace_history_size
]));
159 static const struct command_registration trace_exec_command_handlers
[] = {
162 .handler
= handle_trace_history_command
,
163 .mode
= COMMAND_EXEC
,
164 .help
= "display trace history, clear history or set size",
165 .usage
= "['clear'|size]",
169 .handler
= handle_trace_point_command
,
170 .mode
= COMMAND_EXEC
,
171 .help
= "display trace points, clear list of trace points, "
172 "or add new tracepoint at address",
173 .usage
= "['clear'|address]",
175 COMMAND_REGISTRATION_DONE
177 static const struct command_registration trace_command_handlers
[] = {
180 .mode
= COMMAND_EXEC
,
181 .help
= "trace command group",
182 .chain
= trace_exec_command_handlers
,
184 COMMAND_REGISTRATION_DONE
187 int trace_register_commands(struct command_context
*cmd_ctx
)
189 return register_commands(cmd_ctx
, NULL
, trace_command_handlers
);