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 ***************************************************************************/
25 #include <helper/log.h>
29 int trace_point(struct target
*target
, uint32_t number
)
31 struct trace
*trace
= target
->trace_info
;
33 LOG_DEBUG("tracepoint: %i", (int)number
);
35 if (number
< trace
->num_trace_points
)
36 trace
->trace_points
[number
].hit_counter
++;
38 if (trace
->trace_history_size
) {
39 trace
->trace_history
[trace
->trace_history_pos
++] = number
;
40 if (trace
->trace_history_pos
== trace
->trace_history_size
) {
41 trace
->trace_history_pos
= 0;
42 trace
->trace_history_overflowed
= 1;
49 COMMAND_HANDLER(handle_trace_point_command
)
51 struct target
*target
= get_current_target(CMD_CTX
);
52 struct trace
*trace
= target
->trace_info
;
57 for (i
= 0; i
< trace
->num_trace_points
; i
++) {
58 command_print(CMD_CTX
, "trace point 0x%8.8" PRIx32
" (%lld times hit)",
59 trace
->trace_points
[i
].address
,
60 (long long)trace
->trace_points
[i
].hit_counter
);
66 if (!strcmp(CMD_ARGV
[0], "clear")) {
67 if (trace
->trace_points
) {
68 free(trace
->trace_points
);
69 trace
->trace_points
= NULL
;
71 trace
->num_trace_points
= 0;
72 trace
->trace_points_size
= 0;
77 /* resize array if necessary */
78 if (!trace
->trace_points
|| (trace
->trace_points_size
== trace
->num_trace_points
)) {
79 trace
->trace_points
= realloc(trace
->trace_points
,
80 sizeof(struct trace_point
) * (trace
->trace_points_size
+ 32));
81 trace
->trace_points_size
+= 32;
85 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
86 trace
->trace_points
[trace
->num_trace_points
].address
= address
;
87 trace
->trace_points
[trace
->num_trace_points
].hit_counter
= 0;
88 trace
->num_trace_points
++;
93 COMMAND_HANDLER(handle_trace_history_command
)
95 struct target
*target
= get_current_target(CMD_CTX
);
96 struct trace
*trace
= target
->trace_info
;
99 trace
->trace_history_pos
= 0;
100 trace
->trace_history_overflowed
= 0;
102 if (!strcmp(CMD_ARGV
[0], "clear")) {
103 /* clearing is implicit, we've just reset position anyway */
107 if (trace
->trace_history
)
108 free(trace
->trace_history
);
110 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], trace
->trace_history_size
);
111 trace
->trace_history
= malloc(sizeof(uint32_t) * trace
->trace_history_size
);
113 command_print(CMD_CTX
, "new trace history size: %i", (int)(trace
->trace_history_size
));
117 uint32_t last
= trace
->trace_history_pos
;
119 if (!trace
->trace_history_size
) {
120 command_print(CMD_CTX
, "trace history buffer is not allocated");
124 if (trace
->trace_history_overflowed
) {
125 first
= trace
->trace_history_pos
;
126 last
= trace
->trace_history_pos
- 1;
129 for (i
= first
; (i
% trace
->trace_history_size
) != last
; i
++) {
130 if (trace
->trace_history
[i
% trace
->trace_history_size
] < trace
->num_trace_points
) {
132 address
= trace
->trace_points
[trace
->trace_history
[i
% trace
->trace_history_size
]].address
;
133 command_print(CMD_CTX
, "trace point %i: 0x%8.8" PRIx32
"",
134 (int)(trace
->trace_history
[i
% trace
->trace_history_size
]),
137 command_print(CMD_CTX
, "trace point %i: -not defined-",
138 (int)(trace
->trace_history
[i
% trace
->trace_history_size
]));
145 static const struct command_registration trace_exec_command_handlers
[] = {
148 .handler
= handle_trace_history_command
,
149 .mode
= COMMAND_EXEC
,
150 .help
= "display trace history, clear history or set size",
151 .usage
= "['clear'|size]",
155 .handler
= handle_trace_point_command
,
156 .mode
= COMMAND_EXEC
,
157 .help
= "display trace points, clear list of trace points, "
158 "or add new tracepoint at address",
159 .usage
= "['clear'|address]",
161 COMMAND_REGISTRATION_DONE
163 static const struct command_registration trace_command_handlers
[] = {
166 .mode
= COMMAND_EXEC
,
167 .help
= "trace command group",
169 .chain
= trace_exec_command_handlers
,
171 COMMAND_REGISTRATION_DONE
174 int trace_register_commands(struct command_context
*cmd_ctx
)
176 return register_commands(cmd_ctx
, NULL
, trace_command_handlers
);