1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2005, 2007 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 ***************************************************************************/
12 #include <helper/log.h>
16 int trace_point(struct target
*target
, uint32_t number
)
18 struct trace
*trace
= target
->trace_info
;
20 LOG_DEBUG("tracepoint: %i", (int)number
);
22 if (number
< trace
->num_trace_points
)
23 trace
->trace_points
[number
].hit_counter
++;
25 if (trace
->trace_history_size
) {
26 trace
->trace_history
[trace
->trace_history_pos
++] = number
;
27 if (trace
->trace_history_pos
== trace
->trace_history_size
) {
28 trace
->trace_history_pos
= 0;
29 trace
->trace_history_overflowed
= 1;
36 COMMAND_HANDLER(handle_trace_point_command
)
38 struct target
*target
= get_current_target(CMD_CTX
);
39 struct trace
*trace
= target
->trace_info
;
44 for (i
= 0; i
< trace
->num_trace_points
; i
++) {
45 command_print(CMD
, "trace point 0x%8.8" PRIx32
" (%lld times hit)",
46 trace
->trace_points
[i
].address
,
47 (long long)trace
->trace_points
[i
].hit_counter
);
53 if (!strcmp(CMD_ARGV
[0], "clear")) {
54 free(trace
->trace_points
);
55 trace
->trace_points
= NULL
;
57 trace
->num_trace_points
= 0;
58 trace
->trace_points_size
= 0;
63 /* resize array if necessary */
64 if (!trace
->trace_points
|| (trace
->trace_points_size
== trace
->num_trace_points
)) {
65 trace
->trace_points
= realloc(trace
->trace_points
,
66 sizeof(struct trace_point
) * (trace
->trace_points_size
+ 32));
67 trace
->trace_points_size
+= 32;
71 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
72 trace
->trace_points
[trace
->num_trace_points
].address
= address
;
73 trace
->trace_points
[trace
->num_trace_points
].hit_counter
= 0;
74 trace
->num_trace_points
++;
79 COMMAND_HANDLER(handle_trace_history_command
)
81 struct target
*target
= get_current_target(CMD_CTX
);
82 struct trace
*trace
= target
->trace_info
;
85 trace
->trace_history_pos
= 0;
86 trace
->trace_history_overflowed
= 0;
88 if (!strcmp(CMD_ARGV
[0], "clear")) {
89 /* clearing is implicit, we've just reset position anyway */
93 free(trace
->trace_history
);
95 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], trace
->trace_history_size
);
96 trace
->trace_history
= malloc(sizeof(uint32_t) * trace
->trace_history_size
);
98 command_print(CMD
, "new trace history size: %i", (int)(trace
->trace_history_size
));
102 uint32_t last
= trace
->trace_history_pos
;
104 if (!trace
->trace_history_size
) {
105 command_print(CMD
, "trace history buffer is not allocated");
109 if (trace
->trace_history_overflowed
) {
110 first
= trace
->trace_history_pos
;
111 last
= trace
->trace_history_pos
- 1;
114 for (i
= first
; (i
% trace
->trace_history_size
) != last
; i
++) {
115 if (trace
->trace_history
[i
% trace
->trace_history_size
] < trace
->num_trace_points
) {
117 address
= trace
->trace_points
[trace
->trace_history
[i
% trace
->trace_history_size
]].address
;
118 command_print(CMD
, "trace point %i: 0x%8.8" PRIx32
"",
119 (int)(trace
->trace_history
[i
% trace
->trace_history_size
]),
122 command_print(CMD
, "trace point %i: -not defined-",
123 (int)(trace
->trace_history
[i
% trace
->trace_history_size
]));
130 static const struct command_registration trace_exec_command_handlers
[] = {
133 .handler
= handle_trace_history_command
,
134 .mode
= COMMAND_EXEC
,
135 .help
= "display trace history, clear history or set size",
136 .usage
= "['clear'|size]",
140 .handler
= handle_trace_point_command
,
141 .mode
= COMMAND_EXEC
,
142 .help
= "display trace points, clear list of trace points, "
143 "or add new tracepoint at address",
144 .usage
= "['clear'|address]",
146 COMMAND_REGISTRATION_DONE
148 static const struct command_registration trace_command_handlers
[] = {
151 .mode
= COMMAND_EXEC
,
152 .help
= "trace command group",
154 .chain
= trace_exec_command_handlers
,
156 COMMAND_REGISTRATION_DONE
159 int trace_register_commands(struct command_context
*cmd_ctx
)
161 return register_commands(cmd_ctx
, NULL
, trace_command_handlers
);