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, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
23 #include <helper/log.h>
27 int trace_point(struct target
*target
, uint32_t number
)
29 struct trace
*trace
= target
->trace_info
;
31 LOG_DEBUG("tracepoint: %i", (int)number
);
33 if (number
< trace
->num_trace_points
)
34 trace
->trace_points
[number
].hit_counter
++;
36 if (trace
->trace_history_size
) {
37 trace
->trace_history
[trace
->trace_history_pos
++] = number
;
38 if (trace
->trace_history_pos
== trace
->trace_history_size
) {
39 trace
->trace_history_pos
= 0;
40 trace
->trace_history_overflowed
= 1;
47 COMMAND_HANDLER(handle_trace_point_command
)
49 struct target
*target
= get_current_target(CMD_CTX
);
50 struct trace
*trace
= target
->trace_info
;
55 for (i
= 0; i
< trace
->num_trace_points
; i
++) {
56 command_print(CMD_CTX
, "trace point 0x%8.8" PRIx32
" (%lld times hit)",
57 trace
->trace_points
[i
].address
,
58 (long long)trace
->trace_points
[i
].hit_counter
);
64 if (!strcmp(CMD_ARGV
[0], "clear")) {
65 if (trace
->trace_points
) {
66 free(trace
->trace_points
);
67 trace
->trace_points
= NULL
;
69 trace
->num_trace_points
= 0;
70 trace
->trace_points_size
= 0;
75 /* resize array if necessary */
76 if (!trace
->trace_points
|| (trace
->trace_points_size
== trace
->num_trace_points
)) {
77 trace
->trace_points
= realloc(trace
->trace_points
,
78 sizeof(struct trace_point
) * (trace
->trace_points_size
+ 32));
79 trace
->trace_points_size
+= 32;
83 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
84 trace
->trace_points
[trace
->num_trace_points
].address
= address
;
85 trace
->trace_points
[trace
->num_trace_points
].hit_counter
= 0;
86 trace
->num_trace_points
++;
91 COMMAND_HANDLER(handle_trace_history_command
)
93 struct target
*target
= get_current_target(CMD_CTX
);
94 struct trace
*trace
= target
->trace_info
;
97 trace
->trace_history_pos
= 0;
98 trace
->trace_history_overflowed
= 0;
100 if (!strcmp(CMD_ARGV
[0], "clear")) {
101 /* clearing is implicit, we've just reset position anyway */
105 if (trace
->trace_history
)
106 free(trace
->trace_history
);
108 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], trace
->trace_history_size
);
109 trace
->trace_history
= malloc(sizeof(uint32_t) * trace
->trace_history_size
);
111 command_print(CMD_CTX
, "new trace history size: %i", (int)(trace
->trace_history_size
));
115 uint32_t last
= trace
->trace_history_pos
;
117 if (!trace
->trace_history_size
) {
118 command_print(CMD_CTX
, "trace history buffer is not allocated");
122 if (trace
->trace_history_overflowed
) {
123 first
= trace
->trace_history_pos
;
124 last
= trace
->trace_history_pos
- 1;
127 for (i
= first
; (i
% trace
->trace_history_size
) != last
; i
++) {
128 if (trace
->trace_history
[i
% trace
->trace_history_size
] < trace
->num_trace_points
) {
130 address
= trace
->trace_points
[trace
->trace_history
[i
% trace
->trace_history_size
]].address
;
131 command_print(CMD_CTX
, "trace point %i: 0x%8.8" PRIx32
"",
132 (int)(trace
->trace_history
[i
% trace
->trace_history_size
]),
135 command_print(CMD_CTX
, "trace point %i: -not defined-",
136 (int)(trace
->trace_history
[i
% trace
->trace_history_size
]));
143 static const struct command_registration trace_exec_command_handlers
[] = {
146 .handler
= handle_trace_history_command
,
147 .mode
= COMMAND_EXEC
,
148 .help
= "display trace history, clear history or set size",
149 .usage
= "['clear'|size]",
153 .handler
= handle_trace_point_command
,
154 .mode
= COMMAND_EXEC
,
155 .help
= "display trace points, clear list of trace points, "
156 "or add new tracepoint at address",
157 .usage
= "['clear'|address]",
159 COMMAND_REGISTRATION_DONE
161 static const struct command_registration trace_command_handlers
[] = {
164 .mode
= COMMAND_EXEC
,
165 .help
= "trace command group",
167 .chain
= trace_exec_command_handlers
,
169 COMMAND_REGISTRATION_DONE
172 int trace_register_commands(struct command_context
*cmd_ctx
)
174 return register_commands(cmd_ctx
, NULL
, trace_command_handlers
);