1 /***************************************************************************
2 * Copyright (C) 2011 by Broadcom Corporation *
3 * Evan Hunter - ehunter@broadcom.com *
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 ***************************************************************************/
26 #include "target/target.h"
27 #include "helper/log.h"
28 #include "server/gdb_server.h"
30 static void hex_to_str(char *dst
, char *hex_src
);
33 extern struct rtos_type FreeRTOS_rtos
;
34 extern struct rtos_type ThreadX_rtos
;
35 extern struct rtos_type eCos_rtos
;
36 extern struct rtos_type Linux_os
;
38 static struct rtos_type
*rtos_types
[] = {
46 int rtos_thread_packet(struct connection
*connection
, char *packet
, int packet_size
);
48 int rtos_smp_init(struct target
*target
)
50 if (target
->rtos
->type
->smp_init
)
51 return target
->rtos
->type
->smp_init(target
);
52 return ERROR_TARGET_INIT_FAILED
;
55 static int os_alloc(struct target
*target
, struct rtos_type
*ostype
)
57 struct rtos
*os
= target
->rtos
= calloc(1, sizeof(struct rtos
));
63 os
->current_threadid
= -1;
64 os
->current_thread
= 0;
68 /* RTOS drivers can override the packet handler in _create(). */
69 os
->gdb_thread_packet
= rtos_thread_packet
;
74 static void os_free(struct target
*target
)
79 if (target
->rtos
->symbols
)
80 free(target
->rtos
->symbols
);
86 static int os_alloc_create(struct target
*target
, struct rtos_type
*ostype
)
88 int ret
= os_alloc(target
, ostype
);
91 ret
= target
->rtos
->type
->create(target
);
99 int rtos_create(Jim_GetOptInfo
*goi
, struct target
*target
)
105 if (!goi
->isconfigure
&& goi
->argc
!= 0) {
106 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
, "NO PARAMS");
112 Jim_GetOpt_String(goi
, &cp
, NULL
);
114 if (0 == strcmp(cp
, "auto")) {
115 /* Auto detect tries to look up all symbols for each RTOS,
116 * and runs the RTOS driver's _detect() function when GDB
117 * finds all symbols for any RTOS. See rtos_qsymbol(). */
118 target
->rtos_auto_detect
= true;
120 /* rtos_qsymbol() will iterate over all RTOSes. Allocate
121 * target->rtos here, and set it to the first RTOS type. */
122 return os_alloc(target
, rtos_types
[0]);
125 for (x
= 0; rtos_types
[x
]; x
++)
126 if (0 == strcmp(cp
, rtos_types
[x
]->name
))
127 return os_alloc_create(target
, rtos_types
[x
]);
129 Jim_SetResultFormatted(goi
->interp
, "Unknown RTOS type %s, try one of: ", cp
);
130 res
= Jim_GetResult(goi
->interp
);
131 for (x
= 0; rtos_types
[x
]; x
++)
132 Jim_AppendStrings(goi
->interp
, res
, rtos_types
[x
]->name
, ", ", NULL
);
133 Jim_AppendStrings(goi
->interp
, res
, " or auto", NULL
);
138 int gdb_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
140 struct target
*target
= get_target_from_connection(connection
);
141 if (target
->rtos
== NULL
)
142 return rtos_thread_packet(connection
, packet
, packet_size
); /* thread not
144 return target
->rtos
->gdb_thread_packet(connection
, packet
, packet_size
);
147 static char *next_symbol(struct rtos
*os
, char *cur_symbol
, uint64_t cur_addr
)
149 symbol_table_elem_t
*s
;
152 os
->type
->get_symbol_list_to_lookup(&os
->symbols
);
155 return os
->symbols
[0].symbol_name
;
157 for (s
= os
->symbols
; s
->symbol_name
; s
++)
158 if (!strcmp(s
->symbol_name
, cur_symbol
)) {
159 s
->address
= cur_addr
;
161 return s
->symbol_name
;
167 /* rtos_qsymbol() processes and replies to all qSymbol packets from GDB.
169 * GDB sends a qSymbol:: packet (empty address, empty name) to notify
170 * that it can now answer qSymbol::hexcodedname queries, to look up symbols.
172 * If the qSymbol packet has no address that means GDB did not find the
173 * symbol, in which case auto-detect will move on to try the next RTOS.
175 * rtos_qsymbol() then calls the next_symbol() helper function, which
176 * iterates over symbol names for the current RTOS until it finds the
177 * symbol in the received GDB packet, and then returns the next entry
178 * in the list of symbols.
180 * If GDB replied about the last symbol for the RTOS and the RTOS was
181 * specified explicitly, then no further symbol lookup is done. When
182 * auto-detecting, the RTOS driver _detect() function must return success.
184 * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise.
186 int rtos_qsymbol(struct connection
*connection
, char *packet
, int packet_size
)
188 int rtos_detected
= 0;
191 char reply
[GDB_BUFFER_SIZE
], cur_sym
[GDB_BUFFER_SIZE
/ 2] = "", *next_sym
;
192 struct target
*target
= get_target_from_connection(connection
);
193 struct rtos
*os
= target
->rtos
;
195 reply_len
= sprintf(reply
, "OK");
200 if (sscanf(packet
, "qSymbol:%" SCNx64
":", &addr
))
201 hex_to_str(cur_sym
, strchr(packet
+ 8, ':') + 1);
202 else if (target
->rtos_auto_detect
&& !rtos_try_next(target
))
205 next_sym
= next_symbol(os
, cur_sym
, addr
);
207 if (!target
->rtos_auto_detect
) {
212 if (os
->type
->detect_rtos(target
)) {
213 LOG_OUTPUT("Auto-detected RTOS: %s\r\n", os
->type
->name
);
218 if (!rtos_try_next(target
))
221 os
->type
->get_symbol_list_to_lookup(&os
->symbols
);
223 next_sym
= os
->symbols
[0].symbol_name
;
228 if (8 + (strlen(next_sym
) * 2) + 1 > sizeof(reply
)) {
229 LOG_OUTPUT("ERROR: RTOS symbol '%s' name is too long for GDB!", next_sym
);
233 reply_len
= sprintf(reply
, "qSymbol:");
234 reply_len
+= str_to_hex(reply
+ reply_len
, next_sym
);
237 gdb_put_packet(connection
, reply
, reply_len
);
238 return rtos_detected
;
241 int rtos_thread_packet(struct connection
*connection
, char *packet
, int packet_size
)
243 struct target
*target
= get_target_from_connection(connection
);
245 if (strstr(packet
, "qThreadExtraInfo,")) {
246 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
) &&
247 (target
->rtos
->thread_count
!= 0)) {
248 threadid_t threadid
= 0;
250 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
252 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
254 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
255 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
256 if (target
->rtos
->thread_details
[thread_num
].exists
)
262 gdb_put_packet(connection
, "E01", 3); /* thread not found */
266 struct thread_detail
*detail
= &target
->rtos
->thread_details
[found
];
269 if (detail
->display_str
!= NULL
)
270 str_size
+= strlen(detail
->display_str
);
271 if (detail
->thread_name_str
!= NULL
)
272 str_size
+= strlen(detail
->thread_name_str
);
273 if (detail
->extra_info_str
!= NULL
)
274 str_size
+= strlen(detail
->extra_info_str
);
276 char *tmp_str
= (char *) malloc(str_size
+ 7);
277 char *tmp_str_ptr
= tmp_str
;
279 if (detail
->display_str
!= NULL
)
280 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->display_str
);
281 if (detail
->thread_name_str
!= NULL
) {
282 if (tmp_str_ptr
!= tmp_str
)
283 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
284 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", detail
->thread_name_str
);
286 if (detail
->extra_info_str
!= NULL
) {
287 if (tmp_str_ptr
!= tmp_str
)
288 tmp_str_ptr
+= sprintf(tmp_str_ptr
, " : ");
290 sprintf(tmp_str_ptr
, " : %s", detail
->extra_info_str
);
293 assert(strlen(tmp_str
) ==
294 (size_t) (tmp_str_ptr
- tmp_str
));
296 char *hex_str
= (char *) malloc(strlen(tmp_str
)*2 + 1);
297 str_to_hex(hex_str
, tmp_str
);
299 gdb_put_packet(connection
, hex_str
, strlen(hex_str
));
305 gdb_put_packet(connection
, "", 0);
307 } else if (strstr(packet
, "qSymbol")) {
308 if (rtos_qsymbol(connection
, packet
, packet_size
) == 1) {
309 target
->rtos_auto_detect
= false;
310 target
->rtos
->type
->create(target
);
311 target
->rtos
->type
->update_threads(target
->rtos
);
314 } else if (strstr(packet
, "qfThreadInfo")) {
316 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_count
!= 0)) {
318 char *out_str
= (char *) malloc(17 * target
->rtos
->thread_count
+ 5);
319 char *tmp_str
= out_str
;
320 tmp_str
+= sprintf(tmp_str
, "m");
321 for (i
= 0; i
< target
->rtos
->thread_count
; i
++) {
323 tmp_str
+= sprintf(tmp_str
, ",");
324 tmp_str
+= sprintf(tmp_str
, "%016" PRIx64
,
325 target
->rtos
->thread_details
[i
].threadid
);
328 gdb_put_packet(connection
, out_str
, strlen(out_str
));
330 gdb_put_packet(connection
, "", 0);
333 } else if (strstr(packet
, "qsThreadInfo")) {
334 gdb_put_packet(connection
, "l", 1);
336 } else if (strstr(packet
, "qAttached")) {
337 gdb_put_packet(connection
, "1", 1);
339 } else if (strstr(packet
, "qOffsets")) {
340 char offsets
[] = "Text=0;Data=0;Bss=0";
341 gdb_put_packet(connection
, offsets
, sizeof(offsets
)-1);
343 } else if (strstr(packet
, "qC")) {
344 if (target
->rtos
!= NULL
) {
347 size
= snprintf(buffer
, 15, "QC%08X", (int)target
->rtos
->current_thread
);
348 gdb_put_packet(connection
, buffer
, size
);
350 gdb_put_packet(connection
, "QC0", 3);
352 } else if (packet
[0] == 'T') { /* Is thread alive? */
355 sscanf(packet
, "T%" SCNx64
, &threadid
);
356 if ((target
->rtos
!= NULL
) && (target
->rtos
->thread_details
!= NULL
)) {
358 for (thread_num
= 0; thread_num
< target
->rtos
->thread_count
; thread_num
++) {
359 if (target
->rtos
->thread_details
[thread_num
].threadid
== threadid
) {
360 if (target
->rtos
->thread_details
[thread_num
].exists
)
366 gdb_put_packet(connection
, "OK", 2); /* thread alive */
368 gdb_put_packet(connection
, "E01", 3); /* thread not found */
370 } else if (packet
[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
371 * all other operations ) */
372 if ((packet
[1] == 'g') && (target
->rtos
!= NULL
))
373 sscanf(packet
, "Hg%16" SCNx64
, &target
->rtos
->current_threadid
);
374 gdb_put_packet(connection
, "OK", 2);
378 return GDB_THREAD_PACKET_NOT_CONSUMED
;
381 int rtos_get_gdb_reg_list(struct connection
*connection
)
383 struct target
*target
= get_target_from_connection(connection
);
384 int64_t current_threadid
= target
->rtos
->current_threadid
;
385 if ((target
->rtos
!= NULL
) && (current_threadid
!= -1) &&
386 (current_threadid
!= 0) &&
387 ((current_threadid
!= target
->rtos
->current_thread
) ||
388 (target
->smp
))) { /* in smp several current thread are possible */
390 target
->rtos
->type
->get_thread_reg_list(target
->rtos
,
394 if (hex_reg_list
!= NULL
) {
395 gdb_put_packet(connection
, hex_reg_list
, strlen(hex_reg_list
));
403 int rtos_generic_stack_read(struct target
*target
,
404 const struct rtos_register_stacking
*stacking
,
410 int64_t new_stack_ptr
;
414 if (stack_ptr
== 0) {
415 LOG_OUTPUT("Error: null stack pointer in thread\r\n");
419 uint8_t *stack_data
= (uint8_t *) malloc(stacking
->stack_registers_size
);
420 uint32_t address
= stack_ptr
;
422 if (stacking
->stack_growth_direction
== 1)
423 address
-= stacking
->stack_registers_size
;
424 retval
= target_read_buffer(target
, address
, stacking
->stack_registers_size
, stack_data
);
425 if (retval
!= ERROR_OK
) {
426 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
430 LOG_OUTPUT("Stack Data :");
431 for (i
= 0; i
< stacking
->stack_registers_size
; i
++)
432 LOG_OUTPUT("%02X", stack_data
[i
]);
435 for (i
= 0; i
< stacking
->num_output_registers
; i
++)
436 list_size
+= stacking
->register_offsets
[i
].width_bits
/8;
437 *hex_reg_list
= (char *)malloc(list_size
*2 + 1);
438 tmp_str_ptr
= *hex_reg_list
;
439 new_stack_ptr
= stack_ptr
- stacking
->stack_growth_direction
*
440 stacking
->stack_registers_size
;
441 if (stacking
->stack_alignment
!= 0) {
442 /* Align new stack pointer to x byte boundary */
444 (new_stack_ptr
& (~((int64_t) stacking
->stack_alignment
- 1))) +
445 ((stacking
->stack_growth_direction
== -1) ? stacking
->stack_alignment
: 0);
447 for (i
= 0; i
< stacking
->num_output_registers
; i
++) {
449 for (j
= 0; j
< stacking
->register_offsets
[i
].width_bits
/8; j
++) {
450 if (stacking
->register_offsets
[i
].offset
== -1)
451 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x", 0);
452 else if (stacking
->register_offsets
[i
].offset
== -2)
453 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
454 ((uint8_t *)&new_stack_ptr
)[j
]);
456 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%02x",
457 stack_data
[stacking
->register_offsets
[i
].offset
+ j
]);
460 /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
464 int rtos_try_next(struct target
*target
)
466 struct rtos
*os
= target
->rtos
;
467 struct rtos_type
**type
= rtos_types
;
472 while (*type
&& os
->type
!= *type
)
475 if (!*type
|| !*(++type
))
487 static void hex_to_str(char *dst
, char *hex_src
)
492 while (hex_src
[src_pos
] != '\x00') {
493 char hex_char
= hex_src
[src_pos
];
497 10 : (hex_char
>= 'A') ? hex_char
-'A'+10 : hex_char
-'0';
498 if (0 == (src_pos
& 0x01)) {
499 dst
[dst_pos
] = hex_digit_val
;
502 ((unsigned char *)dst
)[dst_pos
] <<= 4;
503 ((unsigned char *)dst
)[dst_pos
] += hex_digit_val
;
511 int str_to_hex(char *hex_dst
, char *src
)
513 char *posptr
= hex_dst
;
515 for (i
= 0; i
< strlen(src
); i
++)
516 posptr
+= sprintf(posptr
, "%02x", (unsigned char)src
[i
]);
517 return posptr
- hex_dst
;
520 int rtos_update_threads(struct target
*target
)
522 if ((target
->rtos
!= NULL
) && (target
->rtos
->type
!= NULL
))
523 target
->rtos
->type
->update_threads(target
->rtos
);
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)