Message ID | 20220420065013.222816-34-npiggin@gmail.com |
---|---|
State | New |
Headers | show |
Series | gdbserver multi-threaded debugging and POWER9/10 support | expand |
On Wed, 20 Apr 2022 at 06:51, Nicholas Piggin <npiggin@gmail.com> wrote: > > This implements the threadinfo gdb commands, and removes the > restriction of a single target. > > Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Joel Stanley <joel@jms.id.au> > --- > README.md | 17 +- > src/gdb_parser.rl | 16 +- > src/gdb_parser_precompile.c | 328 +++++++++++++++++++----------------- > src/pdbgproxy.c | 66 +++++++- > src/pdbgproxy.h | 10 +- > 5 files changed, 267 insertions(+), 170 deletions(-) > > diff --git a/README.md b/README.md > index c3447c35..778269a6 100644 > --- a/README.md > +++ b/README.md > @@ -538,13 +538,20 @@ At the moment gdbserver is only supported on P8 and P9 and P10. > > Memory access can only be performed on kernel memory. > > -To run a gdbserver on a P8 machine from a BMC running openbmc: > +To run a gdbserver on a machine from a BMC running OpenBMC: > > -Stop all the threads of the core you want to look at > -$ ./pdbg -d p8 -c11 -a stop > +Stop all the threads of the core(s) you want to look at. Ideally all > +threads in the machine should be debugged: > > -Run gdbserver on thread 0 of core 11, accessible through port 44 > -$ ./pdbg -d p8 -p0 -c11 -t0 gdbserver 44 > +$ ./pdbg -a stop > + > +Run gdbserver on the target threads, accessible through port 44 > +$ ./pdbg -a gdbserver 44 > + > +The thread-id tid is set to the PIR of the corresponding thread, the > +hard_smp_processor_id. Be warned, "info threads" or other gdb operations > +that iterate over all threads may be very slow when debugging a lot > +of threads, especially over slow remote links. > > On your local machine: > $ gdb > diff --git a/src/gdb_parser.rl b/src/gdb_parser.rl > index dc1275c3..abb361ae 100644 > --- a/src/gdb_parser.rl > +++ b/src/gdb_parser.rl > @@ -111,14 +111,15 @@ > > # TODO: We don't actually listen to what's supported > q_attached = ('qAttached:' xdigit* @{rsp = "1";}); > - q_C = ('qC' @{rsp = "QC1";}); > - q_supported = ('qSupported:' any* >{rsp = "multiprocess+;vContSupported+;QStartNoAckMode+"; ack_mode = true;}); > - qf_threadinfo = ('qfThreadInfo' @{rsp = "m1l";}); > + q_supported = ('qSupported:' any* >{rsp = "multiprocess+;swbreak+;hwbreak-;qRelocInsn-;vContSupported+;QThreadEvents-;no-resumed-;QStartNoAckMode+"; ack_mode = true;}); > q_start_noack = ('QStartNoAckMode' @{rsp = "OK"; send_ack(priv); ack_mode = false;}); > > # thread info > + is_alive = ('T' ('p' xdigit+ '.')+ xdigit+ @{rsp = "OK";}); > get_thread = ('qC' @{cmd = GET_THREAD;}); > set_thread = ('Hg' ('p' xdigit+ '.')+ xdigit+ $hex_digit %push @{cmd = SET_THREAD;}); > + qf_threadinfo = ('qfThreadInfo' @{cmd = QF_THREADINFO;}); > + qs_threadinfo = ('qsThreadInfo' @{cmd = QS_THREADINFO;}); > > # vCont packet parsing > v_contq = ('vCont?' @{rsp = "vCont;c;C;s;S";}); > @@ -128,9 +129,12 @@ > > interrupt = (3 @{ if (command_callbacks) command_callbacks[INTERRUPT](stack, priv); PR_INFO("RAGEL:interrupt\n");}); > > - commands = (get_mem | get_gprs | get_spr | stop_reason | get_thread | set_thread | > - q_attached | q_C | q_supported | qf_threadinfo | q_C | > - q_start_noack | v_contq | v_contc | v_conts | put_mem | > + commands = (get_gprs | get_spr | > + q_attached | q_supported | q_start_noack | > + stop_reason | is_alive | get_thread | set_thread | > + v_contq | v_contc | v_conts | > + qf_threadinfo | qs_threadinfo | > + get_mem | put_mem | > detach | unknown ); > > cmd = (('$' ((commands & ^'#'*) >reset $crc) > diff --git a/src/gdb_parser_precompile.c b/src/gdb_parser_precompile.c > index 567f1dd6..13c89c9a 100644 > --- a/src/gdb_parser_precompile.c > +++ b/src/gdb_parser_precompile.c > @@ -11,7 +11,7 @@ > #include "debug.h" > > > -#line 145 "src/gdb_parser.rl" > +#line 149 "src/gdb_parser.rl" > > > static enum gdb_command cmd = NONE; > @@ -31,76 +31,86 @@ static bool ack_mode = true; > #line 32 "src/gdb_parser_precompile.c" > static const char _gdb_actions[] = { > 0, 1, 0, 1, 1, 1, 2, 1, > - 3, 1, 15, 1, 23, 1, 24, 1, > - 25, 1, 26, 2, 0, 1, 2, 2, > + 3, 1, 14, 1, 24, 1, 25, 1, > + 26, 1, 27, 2, 0, 1, 2, 2, > 1, 2, 3, 1, 2, 3, 5, 2, > - 4, 1, 2, 13, 1, 2, 15, 1, > - 2, 16, 1, 2, 17, 1, 2, 20, > - 1, 2, 21, 1, 2, 22, 1, 3, > - 0, 6, 1, 3, 0, 7, 1, 3, > - 0, 9, 1, 3, 0, 10, 1, 3, > - 0, 11, 1, 3, 0, 12, 1, 3, > - 2, 8, 1, 3, 3, 19, 1, 3, > - 18, 14, 1 > + 4, 1, 2, 13, 1, 2, 14, 1, > + 2, 15, 1, 2, 16, 1, 2, 17, > + 1, 2, 19, 1, 2, 20, 1, 2, > + 21, 1, 2, 22, 1, 2, 23, 1, > + 3, 0, 6, 1, 3, 0, 7, 1, > + 3, 0, 9, 1, 3, 0, 10, 1, > + 3, 0, 11, 1, 3, 0, 12, 1, > + 3, 2, 8, 1, 3, 3, 18, 1 > + > }; > > -static const unsigned char _gdb_key_offsets[] = { > - 0, 0, 11, 12, 18, 24, 31, 38, > - 40, 42, 49, 57, 65, 72, 79, 87, > - 94, 102, 109, 111, 113, 115, 117, 119, > - 121, 123, 125, 127, 129, 131, 133, 135, > - 137, 144, 152, 157, 159, 161, 163, 165, > - 167, 169, 171, 173, 180, 182, 184, 186, > - 188, 190, 192, 194, 196, 198, 199, 201, > - 203, 205, 207, 209, 211, 213, 215, 217, > - 219, 221, 223, 225, 227, 230, 233, 234, > - 235 > +static const short _gdb_key_offsets[] = { > + 0, 0, 12, 13, 19, 25, 32, 39, > + 41, 43, 50, 58, 66, 73, 80, 88, > + 95, 103, 110, 112, 114, 116, 118, 120, > + 122, 124, 126, 128, 130, 132, 134, 136, > + 138, 140, 147, 155, 163, 170, 177, 185, > + 191, 193, 195, 197, 199, 201, 203, 205, > + 207, 214, 216, 218, 220, 222, 224, 226, > + 228, 230, 232, 233, 235, 237, 239, 241, > + 243, 245, 247, 249, 251, 253, 255, 257, > + 259, 261, 263, 265, 267, 269, 271, 273, > + 275, 277, 279, 281, 284, 287, 288, 289 > }; > > static const char _gdb_trans_keys[] = { > - 35, 63, 68, 72, 77, 81, 103, 109, > - 112, 113, 118, 35, 48, 57, 65, 70, > - 97, 102, 48, 57, 65, 70, 97, 102, > - 35, 48, 57, 65, 70, 97, 102, 35, > - 48, 57, 65, 70, 97, 102, 35, 103, > - 35, 112, 35, 48, 57, 65, 70, 97, > - 102, 35, 46, 48, 57, 65, 70, 97, > - 102, 35, 112, 48, 57, 65, 70, 97, > + 35, 63, 68, 72, 77, 81, 84, 103, > + 109, 112, 113, 118, 35, 48, 57, 65, > + 70, 97, 102, 48, 57, 65, 70, 97, > 102, 35, 48, 57, 65, 70, 97, 102, > 35, 48, 57, 65, 70, 97, 102, 35, > - 44, 48, 57, 65, 70, 97, 102, 35, > - 48, 57, 65, 70, 97, 102, 35, 58, > - 48, 57, 65, 70, 97, 102, 35, 48, > - 57, 65, 70, 97, 102, 35, 83, 35, > - 116, 35, 97, 35, 114, 35, 116, 35, > - 78, 35, 111, 35, 65, 35, 99, 35, > - 107, 35, 77, 35, 111, 35, 100, 35, > - 101, 35, 48, 57, 65, 70, 97, 102, > + 103, 35, 112, 35, 48, 57, 65, 70, > + 97, 102, 35, 46, 48, 57, 65, 70, > + 97, 102, 35, 112, 48, 57, 65, 70, > + 97, 102, 35, 48, 57, 65, 70, 97, > + 102, 35, 48, 57, 65, 70, 97, 102, > 35, 44, 48, 57, 65, 70, 97, 102, > - 35, 65, 67, 83, 102, 35, 116, 35, > - 116, 35, 97, 35, 99, 35, 104, 35, > - 101, 35, 100, 35, 58, 35, 48, 57, > - 65, 70, 97, 102, 35, 117, 35, 112, > - 35, 112, 35, 111, 35, 114, 35, 116, > - 35, 101, 35, 100, 35, 58, 35, 35, > - 84, 35, 104, 35, 114, 35, 101, 35, > - 97, 35, 100, 35, 73, 35, 110, 35, > - 102, 35, 111, 35, 67, 35, 111, 35, > - 110, 35, 116, 35, 59, 63, 35, 99, > - 115, 35, 35, 3, 36, 43, 45, 0 > + 35, 48, 57, 65, 70, 97, 102, 35, > + 58, 48, 57, 65, 70, 97, 102, 35, > + 48, 57, 65, 70, 97, 102, 35, 83, > + 35, 116, 35, 97, 35, 114, 35, 116, > + 35, 78, 35, 111, 35, 65, 35, 99, > + 35, 107, 35, 77, 35, 111, 35, 100, > + 35, 101, 35, 112, 35, 48, 57, 65, > + 70, 97, 102, 35, 46, 48, 57, 65, > + 70, 97, 102, 35, 112, 48, 57, 65, > + 70, 97, 102, 35, 48, 57, 65, 70, > + 97, 102, 35, 48, 57, 65, 70, 97, > + 102, 35, 44, 48, 57, 65, 70, 97, > + 102, 35, 65, 67, 83, 102, 115, 35, > + 116, 35, 116, 35, 97, 35, 99, 35, > + 104, 35, 101, 35, 100, 35, 58, 35, > + 48, 57, 65, 70, 97, 102, 35, 117, > + 35, 112, 35, 112, 35, 111, 35, 114, > + 35, 116, 35, 101, 35, 100, 35, 58, > + 35, 35, 84, 35, 104, 35, 114, 35, > + 101, 35, 97, 35, 100, 35, 73, 35, > + 110, 35, 102, 35, 111, 35, 84, 35, > + 104, 35, 114, 35, 101, 35, 97, 35, > + 100, 35, 73, 35, 110, 35, 102, 35, > + 111, 35, 67, 35, 111, 35, 110, 35, > + 116, 35, 59, 63, 35, 99, 115, 35, > + 35, 3, 36, 43, 45, 0 > }; > > static const char _gdb_single_lengths[] = { > - 0, 11, 1, 0, 0, 1, 1, 2, > + 0, 12, 1, 0, 0, 1, 1, 2, > 2, 1, 2, 2, 1, 1, 2, 1, > 2, 1, 2, 2, 2, 2, 2, 2, > 2, 2, 2, 2, 2, 2, 2, 2, > - 1, 2, 5, 2, 2, 2, 2, 2, > - 2, 2, 2, 1, 2, 2, 2, 2, > - 2, 2, 2, 2, 2, 1, 2, 2, > + 2, 1, 2, 2, 1, 1, 2, 6, > 2, 2, 2, 2, 2, 2, 2, 2, > - 2, 2, 2, 2, 3, 3, 1, 1, > - 4 > + 1, 2, 2, 2, 2, 2, 2, 2, > + 2, 2, 1, 2, 2, 2, 2, 2, > + 2, 2, 2, 2, 2, 2, 2, 2, > + 2, 2, 2, 2, 2, 2, 2, 2, > + 2, 2, 2, 3, 3, 1, 1, 4 > }; > > static const char _gdb_range_lengths[] = { > @@ -108,111 +118,125 @@ static const char _gdb_range_lengths[] = { > 0, 3, 3, 3, 3, 3, 3, 3, > 3, 3, 0, 0, 0, 0, 0, 0, > 0, 0, 0, 0, 0, 0, 0, 0, > - 3, 3, 0, 0, 0, 0, 0, 0, > - 0, 0, 0, 3, 0, 0, 0, 0, > + 0, 3, 3, 3, 3, 3, 3, 0, > 0, 0, 0, 0, 0, 0, 0, 0, > + 3, 0, 0, 0, 0, 0, 0, 0, > 0, 0, 0, 0, 0, 0, 0, 0, > 0, 0, 0, 0, 0, 0, 0, 0, > - 0 > + 0, 0, 0, 0, 0, 0, 0, 0, > + 0, 0, 0, 0, 0, 0, 0, 0 > }; > > static const short _gdb_index_offsets[] = { > - 0, 0, 12, 14, 18, 22, 27, 32, > - 35, 38, 43, 49, 55, 60, 65, 71, > - 76, 82, 87, 90, 93, 96, 99, 102, > - 105, 108, 111, 114, 117, 120, 123, 126, > - 129, 134, 140, 146, 149, 152, 155, 158, > - 161, 164, 167, 170, 175, 178, 181, 184, > - 187, 190, 193, 196, 199, 202, 204, 207, > - 210, 213, 216, 219, 222, 225, 228, 231, > - 234, 237, 240, 243, 246, 250, 254, 256, > - 258 > + 0, 0, 13, 15, 19, 23, 28, 33, > + 36, 39, 44, 50, 56, 61, 66, 72, > + 77, 83, 88, 91, 94, 97, 100, 103, > + 106, 109, 112, 115, 118, 121, 124, 127, > + 130, 133, 138, 144, 150, 155, 160, 166, > + 173, 176, 179, 182, 185, 188, 191, 194, > + 197, 202, 205, 208, 211, 214, 217, 220, > + 223, 226, 229, 231, 234, 237, 240, 243, > + 246, 249, 252, 255, 258, 261, 264, 267, > + 270, 273, 276, 279, 282, 285, 288, 291, > + 294, 297, 300, 303, 307, 311, 313, 315 > }; > > static const char _gdb_indicies[] = { > 1, 2, 3, 4, 5, 6, 7, 8, > - 9, 10, 11, 0, 13, 12, 14, 14, > - 14, 15, 16, 16, 16, 15, 13, 17, > - 17, 17, 12, 18, 17, 17, 17, 12, > - 13, 19, 12, 13, 20, 12, 13, 21, > - 21, 21, 12, 13, 22, 21, 21, 21, > - 12, 13, 20, 23, 23, 23, 12, 18, > - 23, 23, 23, 12, 13, 24, 24, 24, > - 12, 13, 25, 24, 24, 24, 12, 13, > - 26, 26, 26, 12, 13, 27, 26, 26, > - 26, 12, 13, 28, 28, 28, 12, 13, > - 29, 12, 13, 30, 12, 13, 31, 12, > - 13, 32, 12, 13, 33, 12, 13, 34, > - 12, 13, 35, 12, 13, 36, 12, 13, > - 37, 12, 13, 38, 12, 13, 39, 12, > - 13, 40, 12, 13, 41, 12, 13, 42, > - 12, 13, 43, 43, 43, 12, 13, 44, > - 43, 43, 43, 12, 13, 45, 46, 47, > - 48, 12, 13, 49, 12, 13, 50, 12, > - 13, 51, 12, 13, 52, 12, 13, 53, > - 12, 13, 54, 12, 13, 55, 12, 13, > - 56, 12, 13, 57, 57, 57, 12, 13, > - 58, 12, 13, 59, 12, 13, 60, 12, > - 13, 61, 12, 13, 62, 12, 13, 63, > - 12, 13, 64, 12, 13, 65, 12, 13, > - 66, 12, 68, 67, 13, 69, 12, 13, > - 70, 12, 13, 71, 12, 13, 72, 12, > - 13, 73, 12, 13, 74, 12, 13, 75, > - 12, 13, 76, 12, 13, 77, 12, 13, > - 78, 12, 13, 79, 12, 13, 80, 12, > - 13, 81, 12, 13, 82, 12, 13, 83, > - 84, 12, 13, 85, 86, 12, 13, 87, > - 13, 88, 89, 90, 91, 92, 15, 0 > + 9, 10, 11, 12, 0, 14, 13, 15, > + 15, 15, 16, 17, 17, 17, 16, 14, > + 18, 18, 18, 13, 19, 18, 18, 18, > + 13, 14, 20, 13, 14, 21, 13, 14, > + 22, 22, 22, 13, 14, 23, 22, 22, > + 22, 13, 14, 21, 24, 24, 24, 13, > + 19, 24, 24, 24, 13, 14, 25, 25, > + 25, 13, 14, 26, 25, 25, 25, 13, > + 14, 27, 27, 27, 13, 14, 28, 27, > + 27, 27, 13, 14, 29, 29, 29, 13, > + 14, 30, 13, 14, 31, 13, 14, 32, > + 13, 14, 33, 13, 14, 34, 13, 14, > + 35, 13, 14, 36, 13, 14, 37, 13, > + 14, 38, 13, 14, 39, 13, 14, 40, > + 13, 14, 41, 13, 14, 42, 13, 14, > + 43, 13, 14, 44, 13, 14, 45, 45, > + 45, 13, 14, 46, 45, 45, 45, 13, > + 14, 44, 47, 47, 47, 13, 14, 47, > + 47, 47, 13, 14, 48, 48, 48, 13, > + 14, 49, 48, 48, 48, 13, 14, 50, > + 51, 52, 53, 54, 13, 14, 55, 13, > + 14, 56, 13, 14, 57, 13, 14, 58, > + 13, 14, 59, 13, 14, 60, 13, 14, > + 61, 13, 14, 62, 13, 14, 63, 63, > + 63, 13, 14, 64, 13, 14, 65, 13, > + 14, 66, 13, 14, 67, 13, 14, 68, > + 13, 14, 69, 13, 14, 70, 13, 14, > + 71, 13, 14, 72, 13, 74, 73, 14, > + 75, 13, 14, 76, 13, 14, 77, 13, > + 14, 78, 13, 14, 79, 13, 14, 80, > + 13, 14, 81, 13, 14, 82, 13, 14, > + 83, 13, 14, 84, 13, 14, 85, 13, > + 14, 86, 13, 14, 87, 13, 14, 88, > + 13, 14, 89, 13, 14, 90, 13, 14, > + 91, 13, 14, 92, 13, 14, 93, 13, > + 14, 94, 13, 14, 95, 13, 14, 96, > + 13, 14, 97, 13, 14, 98, 13, 14, > + 99, 100, 13, 14, 101, 102, 13, 14, > + 103, 14, 104, 105, 106, 107, 108, 16, > + 0 > }; > > static const char _gdb_trans_targs[] = { > - 2, 3, 2, 5, 7, 13, 18, 2, > - 32, 5, 34, 64, 2, 3, 4, 0, > - 72, 6, 3, 8, 9, 10, 11, 12, > - 14, 15, 16, 17, 17, 19, 20, 21, > - 22, 23, 24, 25, 26, 27, 28, 29, > - 30, 31, 2, 33, 5, 35, 2, 44, > - 54, 36, 37, 38, 39, 40, 41, 42, > - 43, 43, 45, 46, 47, 48, 49, 50, > - 51, 52, 53, 2, 3, 55, 56, 57, > - 58, 59, 60, 61, 62, 63, 2, 65, > - 66, 67, 68, 69, 2, 70, 71, 70, > - 71, 72, 1, 72, 72 > + 2, 3, 2, 5, 7, 13, 18, 32, > + 2, 37, 5, 39, 79, 2, 3, 4, > + 0, 87, 6, 3, 8, 9, 10, 11, > + 12, 14, 15, 16, 17, 17, 19, 20, > + 21, 22, 23, 24, 25, 26, 27, 28, > + 29, 30, 31, 2, 33, 34, 35, 36, > + 38, 5, 40, 2, 49, 59, 69, 41, > + 42, 43, 44, 45, 46, 47, 48, 48, > + 50, 51, 52, 53, 54, 55, 56, 57, > + 58, 2, 3, 60, 61, 62, 63, 64, > + 65, 66, 67, 68, 2, 70, 71, 72, > + 73, 74, 75, 76, 77, 78, 2, 80, > + 81, 82, 83, 84, 2, 85, 86, 85, > + 86, 87, 1, 87, 87 > }; > > static const char _gdb_trans_actions[] = { > - 19, 1, 71, 75, 19, 59, 19, 63, > - 55, 67, 19, 19, 3, 0, 7, 0, > - 28, 25, 5, 3, 3, 3, 3, 83, > - 25, 22, 25, 79, 31, 3, 3, 3, > + 19, 1, 80, 84, 19, 68, 19, 19, > + 72, 64, 76, 19, 19, 3, 0, 7, > + 0, 28, 25, 5, 3, 3, 3, 3, > + 92, 25, 22, 25, 88, 31, 3, 3, > 3, 3, 3, 3, 3, 3, 3, 3, > - 3, 3, 43, 25, 22, 3, 87, 3, > + 3, 3, 3, 40, 3, 3, 3, 43, > + 25, 22, 3, 46, 3, 3, 3, 3, > + 3, 3, 3, 3, 3, 3, 3, 34, > 3, 3, 3, 3, 3, 3, 3, 3, > - 3, 34, 3, 3, 3, 3, 3, 3, > - 3, 3, 3, 37, 9, 3, 3, 3, > - 3, 3, 3, 3, 3, 3, 40, 3, > - 3, 3, 3, 3, 46, 3, 3, 49, > - 52, 11, 13, 15, 17 > + 3, 37, 9, 3, 3, 3, 3, 3, > + 3, 3, 3, 3, 49, 3, 3, 3, > + 3, 3, 3, 3, 3, 3, 52, 3, > + 3, 3, 3, 3, 55, 3, 3, 58, > + 61, 11, 13, 15, 17 > }; > > -static const int gdb_start = 72; > -static const int gdb_first_final = 72; > +static const int gdb_start = 87; > +static const int gdb_first_final = 87; > static const int gdb_error = 0; > > -static const int gdb_en_main = 72; > +static const int gdb_en_main = 87; > > > -#line 161 "src/gdb_parser.rl" > +#line 165 "src/gdb_parser.rl" > > void parser_init(command_cb *callbacks) > { > > -#line 211 "src/gdb_parser_precompile.c" > +#line 235 "src/gdb_parser_precompile.c" > { > cs = gdb_start; > } > > -#line 165 "src/gdb_parser.rl" > +#line 169 "src/gdb_parser.rl" > > command_callbacks = callbacks; > } > @@ -223,7 +247,7 @@ int parse_buffer(char *buf, size_t len, void *priv) > char *pe = p + len; > > > -#line 227 "src/gdb_parser_precompile.c" > +#line 251 "src/gdb_parser_precompile.c" > { > int _klen; > unsigned int _trans; > @@ -418,57 +442,61 @@ _match: > break; > case 14: > #line 114 "src/gdb_parser.rl" > - {rsp = "QC1";} > + {rsp = "multiprocess+;swbreak+;hwbreak-;qRelocInsn-;vContSupported+;QThreadEvents-;no-resumed-;QStartNoAckMode+"; ack_mode = true;} > break; > case 15: > #line 115 "src/gdb_parser.rl" > - {rsp = "multiprocess+;vContSupported+;QStartNoAckMode+"; ack_mode = true;} > + {rsp = "OK"; send_ack(priv); ack_mode = false;} > break; > case 16: > -#line 116 "src/gdb_parser.rl" > - {rsp = "m1l";} > +#line 118 "src/gdb_parser.rl" > + {rsp = "OK";} > break; > case 17: > -#line 117 "src/gdb_parser.rl" > - {rsp = "OK"; send_ack(priv); ack_mode = false;} > +#line 119 "src/gdb_parser.rl" > + {cmd = GET_THREAD;} > break; > case 18: > #line 120 "src/gdb_parser.rl" > - {cmd = GET_THREAD;} > + {cmd = SET_THREAD;} > break; > case 19: > #line 121 "src/gdb_parser.rl" > - {cmd = SET_THREAD;} > + {cmd = QF_THREADINFO;} > break; > case 20: > -#line 124 "src/gdb_parser.rl" > - {rsp = "vCont;c;C;s;S";} > +#line 122 "src/gdb_parser.rl" > + {cmd = QS_THREADINFO;} > break; > case 21: > #line 125 "src/gdb_parser.rl" > - {cmd = V_CONTC;} > + {rsp = "vCont;c;C;s;S";} > break; > case 22: > #line 126 "src/gdb_parser.rl" > - {cmd = V_CONTS;} > + {cmd = V_CONTC;} > break; > case 23: > -#line 129 "src/gdb_parser.rl" > - { if (command_callbacks) command_callbacks[INTERRUPT](stack, priv); PR_INFO("RAGEL:interrupt\n");} > +#line 127 "src/gdb_parser.rl" > + {cmd = V_CONTS;} > break; > case 24: > -#line 137 "src/gdb_parser.rl" > - {PR_INFO("RAGEL:cmd\n");} > +#line 130 "src/gdb_parser.rl" > + { if (command_callbacks) command_callbacks[INTERRUPT](stack, priv); PR_INFO("RAGEL:interrupt\n");} > break; > case 25: > -#line 140 "src/gdb_parser.rl" > - {PR_INFO("RAGEL:ack\n");} > +#line 141 "src/gdb_parser.rl" > + {PR_INFO("RAGEL:cmd\n");} > break; > case 26: > -#line 141 "src/gdb_parser.rl" > +#line 144 "src/gdb_parser.rl" > + {PR_INFO("RAGEL:ack\n");} > + break; > + case 27: > +#line 145 "src/gdb_parser.rl" > {PR_INFO("RAGEL:nack\n");} > break; > -#line 472 "src/gdb_parser_precompile.c" > +#line 500 "src/gdb_parser_precompile.c" > } > } > > @@ -481,7 +509,7 @@ _again: > _out: {} > } > > -#line 175 "src/gdb_parser.rl" > +#line 179 "src/gdb_parser.rl" > > if (cs == gdb_error) { > printf("parse error\n"); > diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c > index 52f34a91..1d24e68a 100644 > --- a/src/pdbgproxy.c > +++ b/src/pdbgproxy.c > @@ -142,6 +142,58 @@ static void set_thread(uint64_t *stack, void *priv) > send_response(fd, ERROR(EEXIST)); > } > > +static int threadinfo_iterator; > + > +static void qs_threadinfo(uint64_t *stack, void *priv) > +{ > + struct pdbg_target *target; > + char data[MAX_RESP_LEN] = "m"; > + size_t s = 1; > + int iter = 0; > + bool found = false; > + > + for_each_path_target_class("thread", target) { > + struct thread *thread = target_to_thread(target); > + struct gdb_thread *gdb_thread = thread->gdbserver_priv; > + > + if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) > + continue; > + > + if (!found && iter < threadinfo_iterator) { > + iter++; > + continue; > + } > + > + found = true; > + > + if (iter == threadinfo_iterator) > + s += snprintf(data + s, sizeof(data) - s, > + "%04" PRIx64, gdb_thread->pir); > + else > + s += snprintf(data + s, sizeof(data) - s, > + ",%04" PRIx64, gdb_thread->pir); > + threadinfo_iterator++; > + > + if (sizeof(data) - s < 9) /* comma, 7 digits, NUL */ > + break; > + > + } > + > + PR_INFO("qf_threadinfo %s\n", data); > + > + if (s > 1) > + send_response(fd, data); > + else > + send_response(fd, "l"); > +} > + > +static void qf_threadinfo(uint64_t *stack, void *priv) > +{ > + threadinfo_iterator = 0; > + > + qs_threadinfo(stack, priv); > +} > + > static void send_stop_for_thread(struct pdbg_target *target) > { > struct thread *thread = target_to_thread(target); > @@ -880,12 +932,14 @@ static command_cb callbacks[LAST_CMD + 1] = { > cmd_default, > get_gprs, > get_spr, > - get_mem, > stop_reason, > get_thread, > set_thread, > v_contc, > v_conts, > + qf_threadinfo, > + qs_threadinfo, > + get_mem, > put_mem, > interrupt, > detach, > @@ -1018,12 +1072,8 @@ static int gdbserver(uint16_t port) > memset(gdb_thread, 0, sizeof(*gdb_thread)); > thread->gdbserver_priv = gdb_thread; > > - if (!first_target) { > + if (!first_target) > first_target = target; > - } else { > - fprintf(stderr, "GDB server cannot be run on multiple threads at once.\n"); > - return 0; > - } > } > > if (!first_target) { > @@ -1039,6 +1089,10 @@ static int gdbserver(uint16_t port) > PR_WARNING("Breakpoints may cause host crashes on POWER9 and should not be used\n"); > } > > + if (!path_target_all_selected("thread", NULL)) { > + PR_WARNING("GDBSERVER works best when targeting all threads (-a)\n"); > + } > + > thread_target = first_target; > > for_each_path_target_class("thread", target) { > diff --git a/src/pdbgproxy.h b/src/pdbgproxy.h > index 2005083d..cafd4cbc 100644 > --- a/src/pdbgproxy.h > +++ b/src/pdbgproxy.h > @@ -1,9 +1,13 @@ > #ifndef __PDBGPROXY_H > #define __PDBGPROXY_H > > -enum gdb_command {NONE, GET_GPRS, GET_SPR, GET_MEM, > - STOP_REASON, GET_THREAD, SET_THREAD, V_CONTC, V_CONTS, > - PUT_MEM, INTERRUPT, DETACH, LAST_CMD}; > +enum gdb_command {NONE, GET_GPRS, GET_SPR, > + STOP_REASON, GET_THREAD, SET_THREAD, > + V_CONTC, V_CONTS, > + QF_THREADINFO, QS_THREADINFO, > + GET_MEM, PUT_MEM, > + INTERRUPT, DETACH, LAST_CMD}; > + > typedef void (*command_cb)(uint64_t *stack, void *priv); > > void parser_init(command_cb *callbacks); > -- > 2.35.1 > > -- > Pdbg mailing list > Pdbg@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/pdbg
diff --git a/README.md b/README.md index c3447c35..778269a6 100644 --- a/README.md +++ b/README.md @@ -538,13 +538,20 @@ At the moment gdbserver is only supported on P8 and P9 and P10. Memory access can only be performed on kernel memory. -To run a gdbserver on a P8 machine from a BMC running openbmc: +To run a gdbserver on a machine from a BMC running OpenBMC: -Stop all the threads of the core you want to look at -$ ./pdbg -d p8 -c11 -a stop +Stop all the threads of the core(s) you want to look at. Ideally all +threads in the machine should be debugged: -Run gdbserver on thread 0 of core 11, accessible through port 44 -$ ./pdbg -d p8 -p0 -c11 -t0 gdbserver 44 +$ ./pdbg -a stop + +Run gdbserver on the target threads, accessible through port 44 +$ ./pdbg -a gdbserver 44 + +The thread-id tid is set to the PIR of the corresponding thread, the +hard_smp_processor_id. Be warned, "info threads" or other gdb operations +that iterate over all threads may be very slow when debugging a lot +of threads, especially over slow remote links. On your local machine: $ gdb diff --git a/src/gdb_parser.rl b/src/gdb_parser.rl index dc1275c3..abb361ae 100644 --- a/src/gdb_parser.rl +++ b/src/gdb_parser.rl @@ -111,14 +111,15 @@ # TODO: We don't actually listen to what's supported q_attached = ('qAttached:' xdigit* @{rsp = "1";}); - q_C = ('qC' @{rsp = "QC1";}); - q_supported = ('qSupported:' any* >{rsp = "multiprocess+;vContSupported+;QStartNoAckMode+"; ack_mode = true;}); - qf_threadinfo = ('qfThreadInfo' @{rsp = "m1l";}); + q_supported = ('qSupported:' any* >{rsp = "multiprocess+;swbreak+;hwbreak-;qRelocInsn-;vContSupported+;QThreadEvents-;no-resumed-;QStartNoAckMode+"; ack_mode = true;}); q_start_noack = ('QStartNoAckMode' @{rsp = "OK"; send_ack(priv); ack_mode = false;}); # thread info + is_alive = ('T' ('p' xdigit+ '.')+ xdigit+ @{rsp = "OK";}); get_thread = ('qC' @{cmd = GET_THREAD;}); set_thread = ('Hg' ('p' xdigit+ '.')+ xdigit+ $hex_digit %push @{cmd = SET_THREAD;}); + qf_threadinfo = ('qfThreadInfo' @{cmd = QF_THREADINFO;}); + qs_threadinfo = ('qsThreadInfo' @{cmd = QS_THREADINFO;}); # vCont packet parsing v_contq = ('vCont?' @{rsp = "vCont;c;C;s;S";}); @@ -128,9 +129,12 @@ interrupt = (3 @{ if (command_callbacks) command_callbacks[INTERRUPT](stack, priv); PR_INFO("RAGEL:interrupt\n");}); - commands = (get_mem | get_gprs | get_spr | stop_reason | get_thread | set_thread | - q_attached | q_C | q_supported | qf_threadinfo | q_C | - q_start_noack | v_contq | v_contc | v_conts | put_mem | + commands = (get_gprs | get_spr | + q_attached | q_supported | q_start_noack | + stop_reason | is_alive | get_thread | set_thread | + v_contq | v_contc | v_conts | + qf_threadinfo | qs_threadinfo | + get_mem | put_mem | detach | unknown ); cmd = (('$' ((commands & ^'#'*) >reset $crc) diff --git a/src/gdb_parser_precompile.c b/src/gdb_parser_precompile.c index 567f1dd6..13c89c9a 100644 --- a/src/gdb_parser_precompile.c +++ b/src/gdb_parser_precompile.c @@ -11,7 +11,7 @@ #include "debug.h" -#line 145 "src/gdb_parser.rl" +#line 149 "src/gdb_parser.rl" static enum gdb_command cmd = NONE; @@ -31,76 +31,86 @@ static bool ack_mode = true; #line 32 "src/gdb_parser_precompile.c" static const char _gdb_actions[] = { 0, 1, 0, 1, 1, 1, 2, 1, - 3, 1, 15, 1, 23, 1, 24, 1, - 25, 1, 26, 2, 0, 1, 2, 2, + 3, 1, 14, 1, 24, 1, 25, 1, + 26, 1, 27, 2, 0, 1, 2, 2, 1, 2, 3, 1, 2, 3, 5, 2, - 4, 1, 2, 13, 1, 2, 15, 1, - 2, 16, 1, 2, 17, 1, 2, 20, - 1, 2, 21, 1, 2, 22, 1, 3, - 0, 6, 1, 3, 0, 7, 1, 3, - 0, 9, 1, 3, 0, 10, 1, 3, - 0, 11, 1, 3, 0, 12, 1, 3, - 2, 8, 1, 3, 3, 19, 1, 3, - 18, 14, 1 + 4, 1, 2, 13, 1, 2, 14, 1, + 2, 15, 1, 2, 16, 1, 2, 17, + 1, 2, 19, 1, 2, 20, 1, 2, + 21, 1, 2, 22, 1, 2, 23, 1, + 3, 0, 6, 1, 3, 0, 7, 1, + 3, 0, 9, 1, 3, 0, 10, 1, + 3, 0, 11, 1, 3, 0, 12, 1, + 3, 2, 8, 1, 3, 3, 18, 1 + }; -static const unsigned char _gdb_key_offsets[] = { - 0, 0, 11, 12, 18, 24, 31, 38, - 40, 42, 49, 57, 65, 72, 79, 87, - 94, 102, 109, 111, 113, 115, 117, 119, - 121, 123, 125, 127, 129, 131, 133, 135, - 137, 144, 152, 157, 159, 161, 163, 165, - 167, 169, 171, 173, 180, 182, 184, 186, - 188, 190, 192, 194, 196, 198, 199, 201, - 203, 205, 207, 209, 211, 213, 215, 217, - 219, 221, 223, 225, 227, 230, 233, 234, - 235 +static const short _gdb_key_offsets[] = { + 0, 0, 12, 13, 19, 25, 32, 39, + 41, 43, 50, 58, 66, 73, 80, 88, + 95, 103, 110, 112, 114, 116, 118, 120, + 122, 124, 126, 128, 130, 132, 134, 136, + 138, 140, 147, 155, 163, 170, 177, 185, + 191, 193, 195, 197, 199, 201, 203, 205, + 207, 214, 216, 218, 220, 222, 224, 226, + 228, 230, 232, 233, 235, 237, 239, 241, + 243, 245, 247, 249, 251, 253, 255, 257, + 259, 261, 263, 265, 267, 269, 271, 273, + 275, 277, 279, 281, 284, 287, 288, 289 }; static const char _gdb_trans_keys[] = { - 35, 63, 68, 72, 77, 81, 103, 109, - 112, 113, 118, 35, 48, 57, 65, 70, - 97, 102, 48, 57, 65, 70, 97, 102, - 35, 48, 57, 65, 70, 97, 102, 35, - 48, 57, 65, 70, 97, 102, 35, 103, - 35, 112, 35, 48, 57, 65, 70, 97, - 102, 35, 46, 48, 57, 65, 70, 97, - 102, 35, 112, 48, 57, 65, 70, 97, + 35, 63, 68, 72, 77, 81, 84, 103, + 109, 112, 113, 118, 35, 48, 57, 65, + 70, 97, 102, 48, 57, 65, 70, 97, 102, 35, 48, 57, 65, 70, 97, 102, 35, 48, 57, 65, 70, 97, 102, 35, - 44, 48, 57, 65, 70, 97, 102, 35, - 48, 57, 65, 70, 97, 102, 35, 58, - 48, 57, 65, 70, 97, 102, 35, 48, - 57, 65, 70, 97, 102, 35, 83, 35, - 116, 35, 97, 35, 114, 35, 116, 35, - 78, 35, 111, 35, 65, 35, 99, 35, - 107, 35, 77, 35, 111, 35, 100, 35, - 101, 35, 48, 57, 65, 70, 97, 102, + 103, 35, 112, 35, 48, 57, 65, 70, + 97, 102, 35, 46, 48, 57, 65, 70, + 97, 102, 35, 112, 48, 57, 65, 70, + 97, 102, 35, 48, 57, 65, 70, 97, + 102, 35, 48, 57, 65, 70, 97, 102, 35, 44, 48, 57, 65, 70, 97, 102, - 35, 65, 67, 83, 102, 35, 116, 35, - 116, 35, 97, 35, 99, 35, 104, 35, - 101, 35, 100, 35, 58, 35, 48, 57, - 65, 70, 97, 102, 35, 117, 35, 112, - 35, 112, 35, 111, 35, 114, 35, 116, - 35, 101, 35, 100, 35, 58, 35, 35, - 84, 35, 104, 35, 114, 35, 101, 35, - 97, 35, 100, 35, 73, 35, 110, 35, - 102, 35, 111, 35, 67, 35, 111, 35, - 110, 35, 116, 35, 59, 63, 35, 99, - 115, 35, 35, 3, 36, 43, 45, 0 + 35, 48, 57, 65, 70, 97, 102, 35, + 58, 48, 57, 65, 70, 97, 102, 35, + 48, 57, 65, 70, 97, 102, 35, 83, + 35, 116, 35, 97, 35, 114, 35, 116, + 35, 78, 35, 111, 35, 65, 35, 99, + 35, 107, 35, 77, 35, 111, 35, 100, + 35, 101, 35, 112, 35, 48, 57, 65, + 70, 97, 102, 35, 46, 48, 57, 65, + 70, 97, 102, 35, 112, 48, 57, 65, + 70, 97, 102, 35, 48, 57, 65, 70, + 97, 102, 35, 48, 57, 65, 70, 97, + 102, 35, 44, 48, 57, 65, 70, 97, + 102, 35, 65, 67, 83, 102, 115, 35, + 116, 35, 116, 35, 97, 35, 99, 35, + 104, 35, 101, 35, 100, 35, 58, 35, + 48, 57, 65, 70, 97, 102, 35, 117, + 35, 112, 35, 112, 35, 111, 35, 114, + 35, 116, 35, 101, 35, 100, 35, 58, + 35, 35, 84, 35, 104, 35, 114, 35, + 101, 35, 97, 35, 100, 35, 73, 35, + 110, 35, 102, 35, 111, 35, 84, 35, + 104, 35, 114, 35, 101, 35, 97, 35, + 100, 35, 73, 35, 110, 35, 102, 35, + 111, 35, 67, 35, 111, 35, 110, 35, + 116, 35, 59, 63, 35, 99, 115, 35, + 35, 3, 36, 43, 45, 0 }; static const char _gdb_single_lengths[] = { - 0, 11, 1, 0, 0, 1, 1, 2, + 0, 12, 1, 0, 0, 1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 2, 5, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 2, 2, + 2, 1, 2, 2, 1, 1, 2, 6, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 3, 3, 1, 1, - 4 + 1, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 1, 1, 4 }; static const char _gdb_range_lengths[] = { @@ -108,111 +118,125 @@ static const char _gdb_range_lengths[] = { 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; static const short _gdb_index_offsets[] = { - 0, 0, 12, 14, 18, 22, 27, 32, - 35, 38, 43, 49, 55, 60, 65, 71, - 76, 82, 87, 90, 93, 96, 99, 102, - 105, 108, 111, 114, 117, 120, 123, 126, - 129, 134, 140, 146, 149, 152, 155, 158, - 161, 164, 167, 170, 175, 178, 181, 184, - 187, 190, 193, 196, 199, 202, 204, 207, - 210, 213, 216, 219, 222, 225, 228, 231, - 234, 237, 240, 243, 246, 250, 254, 256, - 258 + 0, 0, 13, 15, 19, 23, 28, 33, + 36, 39, 44, 50, 56, 61, 66, 72, + 77, 83, 88, 91, 94, 97, 100, 103, + 106, 109, 112, 115, 118, 121, 124, 127, + 130, 133, 138, 144, 150, 155, 160, 166, + 173, 176, 179, 182, 185, 188, 191, 194, + 197, 202, 205, 208, 211, 214, 217, 220, + 223, 226, 229, 231, 234, 237, 240, 243, + 246, 249, 252, 255, 258, 261, 264, 267, + 270, 273, 276, 279, 282, 285, 288, 291, + 294, 297, 300, 303, 307, 311, 313, 315 }; static const char _gdb_indicies[] = { 1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 0, 13, 12, 14, 14, - 14, 15, 16, 16, 16, 15, 13, 17, - 17, 17, 12, 18, 17, 17, 17, 12, - 13, 19, 12, 13, 20, 12, 13, 21, - 21, 21, 12, 13, 22, 21, 21, 21, - 12, 13, 20, 23, 23, 23, 12, 18, - 23, 23, 23, 12, 13, 24, 24, 24, - 12, 13, 25, 24, 24, 24, 12, 13, - 26, 26, 26, 12, 13, 27, 26, 26, - 26, 12, 13, 28, 28, 28, 12, 13, - 29, 12, 13, 30, 12, 13, 31, 12, - 13, 32, 12, 13, 33, 12, 13, 34, - 12, 13, 35, 12, 13, 36, 12, 13, - 37, 12, 13, 38, 12, 13, 39, 12, - 13, 40, 12, 13, 41, 12, 13, 42, - 12, 13, 43, 43, 43, 12, 13, 44, - 43, 43, 43, 12, 13, 45, 46, 47, - 48, 12, 13, 49, 12, 13, 50, 12, - 13, 51, 12, 13, 52, 12, 13, 53, - 12, 13, 54, 12, 13, 55, 12, 13, - 56, 12, 13, 57, 57, 57, 12, 13, - 58, 12, 13, 59, 12, 13, 60, 12, - 13, 61, 12, 13, 62, 12, 13, 63, - 12, 13, 64, 12, 13, 65, 12, 13, - 66, 12, 68, 67, 13, 69, 12, 13, - 70, 12, 13, 71, 12, 13, 72, 12, - 13, 73, 12, 13, 74, 12, 13, 75, - 12, 13, 76, 12, 13, 77, 12, 13, - 78, 12, 13, 79, 12, 13, 80, 12, - 13, 81, 12, 13, 82, 12, 13, 83, - 84, 12, 13, 85, 86, 12, 13, 87, - 13, 88, 89, 90, 91, 92, 15, 0 + 9, 10, 11, 12, 0, 14, 13, 15, + 15, 15, 16, 17, 17, 17, 16, 14, + 18, 18, 18, 13, 19, 18, 18, 18, + 13, 14, 20, 13, 14, 21, 13, 14, + 22, 22, 22, 13, 14, 23, 22, 22, + 22, 13, 14, 21, 24, 24, 24, 13, + 19, 24, 24, 24, 13, 14, 25, 25, + 25, 13, 14, 26, 25, 25, 25, 13, + 14, 27, 27, 27, 13, 14, 28, 27, + 27, 27, 13, 14, 29, 29, 29, 13, + 14, 30, 13, 14, 31, 13, 14, 32, + 13, 14, 33, 13, 14, 34, 13, 14, + 35, 13, 14, 36, 13, 14, 37, 13, + 14, 38, 13, 14, 39, 13, 14, 40, + 13, 14, 41, 13, 14, 42, 13, 14, + 43, 13, 14, 44, 13, 14, 45, 45, + 45, 13, 14, 46, 45, 45, 45, 13, + 14, 44, 47, 47, 47, 13, 14, 47, + 47, 47, 13, 14, 48, 48, 48, 13, + 14, 49, 48, 48, 48, 13, 14, 50, + 51, 52, 53, 54, 13, 14, 55, 13, + 14, 56, 13, 14, 57, 13, 14, 58, + 13, 14, 59, 13, 14, 60, 13, 14, + 61, 13, 14, 62, 13, 14, 63, 63, + 63, 13, 14, 64, 13, 14, 65, 13, + 14, 66, 13, 14, 67, 13, 14, 68, + 13, 14, 69, 13, 14, 70, 13, 14, + 71, 13, 14, 72, 13, 74, 73, 14, + 75, 13, 14, 76, 13, 14, 77, 13, + 14, 78, 13, 14, 79, 13, 14, 80, + 13, 14, 81, 13, 14, 82, 13, 14, + 83, 13, 14, 84, 13, 14, 85, 13, + 14, 86, 13, 14, 87, 13, 14, 88, + 13, 14, 89, 13, 14, 90, 13, 14, + 91, 13, 14, 92, 13, 14, 93, 13, + 14, 94, 13, 14, 95, 13, 14, 96, + 13, 14, 97, 13, 14, 98, 13, 14, + 99, 100, 13, 14, 101, 102, 13, 14, + 103, 14, 104, 105, 106, 107, 108, 16, + 0 }; static const char _gdb_trans_targs[] = { - 2, 3, 2, 5, 7, 13, 18, 2, - 32, 5, 34, 64, 2, 3, 4, 0, - 72, 6, 3, 8, 9, 10, 11, 12, - 14, 15, 16, 17, 17, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 2, 33, 5, 35, 2, 44, - 54, 36, 37, 38, 39, 40, 41, 42, - 43, 43, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 2, 3, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 2, 65, - 66, 67, 68, 69, 2, 70, 71, 70, - 71, 72, 1, 72, 72 + 2, 3, 2, 5, 7, 13, 18, 32, + 2, 37, 5, 39, 79, 2, 3, 4, + 0, 87, 6, 3, 8, 9, 10, 11, + 12, 14, 15, 16, 17, 17, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 2, 33, 34, 35, 36, + 38, 5, 40, 2, 49, 59, 69, 41, + 42, 43, 44, 45, 46, 47, 48, 48, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 2, 3, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 2, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 2, 80, + 81, 82, 83, 84, 2, 85, 86, 85, + 86, 87, 1, 87, 87 }; static const char _gdb_trans_actions[] = { - 19, 1, 71, 75, 19, 59, 19, 63, - 55, 67, 19, 19, 3, 0, 7, 0, - 28, 25, 5, 3, 3, 3, 3, 83, - 25, 22, 25, 79, 31, 3, 3, 3, + 19, 1, 80, 84, 19, 68, 19, 19, + 72, 64, 76, 19, 19, 3, 0, 7, + 0, 28, 25, 5, 3, 3, 3, 3, + 92, 25, 22, 25, 88, 31, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 43, 25, 22, 3, 87, 3, + 3, 3, 3, 40, 3, 3, 3, 43, + 25, 22, 3, 46, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 34, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 34, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 37, 9, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 40, 3, - 3, 3, 3, 3, 46, 3, 3, 49, - 52, 11, 13, 15, 17 + 3, 37, 9, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 49, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 52, 3, + 3, 3, 3, 3, 55, 3, 3, 58, + 61, 11, 13, 15, 17 }; -static const int gdb_start = 72; -static const int gdb_first_final = 72; +static const int gdb_start = 87; +static const int gdb_first_final = 87; static const int gdb_error = 0; -static const int gdb_en_main = 72; +static const int gdb_en_main = 87; -#line 161 "src/gdb_parser.rl" +#line 165 "src/gdb_parser.rl" void parser_init(command_cb *callbacks) { -#line 211 "src/gdb_parser_precompile.c" +#line 235 "src/gdb_parser_precompile.c" { cs = gdb_start; } -#line 165 "src/gdb_parser.rl" +#line 169 "src/gdb_parser.rl" command_callbacks = callbacks; } @@ -223,7 +247,7 @@ int parse_buffer(char *buf, size_t len, void *priv) char *pe = p + len; -#line 227 "src/gdb_parser_precompile.c" +#line 251 "src/gdb_parser_precompile.c" { int _klen; unsigned int _trans; @@ -418,57 +442,61 @@ _match: break; case 14: #line 114 "src/gdb_parser.rl" - {rsp = "QC1";} + {rsp = "multiprocess+;swbreak+;hwbreak-;qRelocInsn-;vContSupported+;QThreadEvents-;no-resumed-;QStartNoAckMode+"; ack_mode = true;} break; case 15: #line 115 "src/gdb_parser.rl" - {rsp = "multiprocess+;vContSupported+;QStartNoAckMode+"; ack_mode = true;} + {rsp = "OK"; send_ack(priv); ack_mode = false;} break; case 16: -#line 116 "src/gdb_parser.rl" - {rsp = "m1l";} +#line 118 "src/gdb_parser.rl" + {rsp = "OK";} break; case 17: -#line 117 "src/gdb_parser.rl" - {rsp = "OK"; send_ack(priv); ack_mode = false;} +#line 119 "src/gdb_parser.rl" + {cmd = GET_THREAD;} break; case 18: #line 120 "src/gdb_parser.rl" - {cmd = GET_THREAD;} + {cmd = SET_THREAD;} break; case 19: #line 121 "src/gdb_parser.rl" - {cmd = SET_THREAD;} + {cmd = QF_THREADINFO;} break; case 20: -#line 124 "src/gdb_parser.rl" - {rsp = "vCont;c;C;s;S";} +#line 122 "src/gdb_parser.rl" + {cmd = QS_THREADINFO;} break; case 21: #line 125 "src/gdb_parser.rl" - {cmd = V_CONTC;} + {rsp = "vCont;c;C;s;S";} break; case 22: #line 126 "src/gdb_parser.rl" - {cmd = V_CONTS;} + {cmd = V_CONTC;} break; case 23: -#line 129 "src/gdb_parser.rl" - { if (command_callbacks) command_callbacks[INTERRUPT](stack, priv); PR_INFO("RAGEL:interrupt\n");} +#line 127 "src/gdb_parser.rl" + {cmd = V_CONTS;} break; case 24: -#line 137 "src/gdb_parser.rl" - {PR_INFO("RAGEL:cmd\n");} +#line 130 "src/gdb_parser.rl" + { if (command_callbacks) command_callbacks[INTERRUPT](stack, priv); PR_INFO("RAGEL:interrupt\n");} break; case 25: -#line 140 "src/gdb_parser.rl" - {PR_INFO("RAGEL:ack\n");} +#line 141 "src/gdb_parser.rl" + {PR_INFO("RAGEL:cmd\n");} break; case 26: -#line 141 "src/gdb_parser.rl" +#line 144 "src/gdb_parser.rl" + {PR_INFO("RAGEL:ack\n");} + break; + case 27: +#line 145 "src/gdb_parser.rl" {PR_INFO("RAGEL:nack\n");} break; -#line 472 "src/gdb_parser_precompile.c" +#line 500 "src/gdb_parser_precompile.c" } } @@ -481,7 +509,7 @@ _again: _out: {} } -#line 175 "src/gdb_parser.rl" +#line 179 "src/gdb_parser.rl" if (cs == gdb_error) { printf("parse error\n"); diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c index 52f34a91..1d24e68a 100644 --- a/src/pdbgproxy.c +++ b/src/pdbgproxy.c @@ -142,6 +142,58 @@ static void set_thread(uint64_t *stack, void *priv) send_response(fd, ERROR(EEXIST)); } +static int threadinfo_iterator; + +static void qs_threadinfo(uint64_t *stack, void *priv) +{ + struct pdbg_target *target; + char data[MAX_RESP_LEN] = "m"; + size_t s = 1; + int iter = 0; + bool found = false; + + for_each_path_target_class("thread", target) { + struct thread *thread = target_to_thread(target); + struct gdb_thread *gdb_thread = thread->gdbserver_priv; + + if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) + continue; + + if (!found && iter < threadinfo_iterator) { + iter++; + continue; + } + + found = true; + + if (iter == threadinfo_iterator) + s += snprintf(data + s, sizeof(data) - s, + "%04" PRIx64, gdb_thread->pir); + else + s += snprintf(data + s, sizeof(data) - s, + ",%04" PRIx64, gdb_thread->pir); + threadinfo_iterator++; + + if (sizeof(data) - s < 9) /* comma, 7 digits, NUL */ + break; + + } + + PR_INFO("qf_threadinfo %s\n", data); + + if (s > 1) + send_response(fd, data); + else + send_response(fd, "l"); +} + +static void qf_threadinfo(uint64_t *stack, void *priv) +{ + threadinfo_iterator = 0; + + qs_threadinfo(stack, priv); +} + static void send_stop_for_thread(struct pdbg_target *target) { struct thread *thread = target_to_thread(target); @@ -880,12 +932,14 @@ static command_cb callbacks[LAST_CMD + 1] = { cmd_default, get_gprs, get_spr, - get_mem, stop_reason, get_thread, set_thread, v_contc, v_conts, + qf_threadinfo, + qs_threadinfo, + get_mem, put_mem, interrupt, detach, @@ -1018,12 +1072,8 @@ static int gdbserver(uint16_t port) memset(gdb_thread, 0, sizeof(*gdb_thread)); thread->gdbserver_priv = gdb_thread; - if (!first_target) { + if (!first_target) first_target = target; - } else { - fprintf(stderr, "GDB server cannot be run on multiple threads at once.\n"); - return 0; - } } if (!first_target) { @@ -1039,6 +1089,10 @@ static int gdbserver(uint16_t port) PR_WARNING("Breakpoints may cause host crashes on POWER9 and should not be used\n"); } + if (!path_target_all_selected("thread", NULL)) { + PR_WARNING("GDBSERVER works best when targeting all threads (-a)\n"); + } + thread_target = first_target; for_each_path_target_class("thread", target) { diff --git a/src/pdbgproxy.h b/src/pdbgproxy.h index 2005083d..cafd4cbc 100644 --- a/src/pdbgproxy.h +++ b/src/pdbgproxy.h @@ -1,9 +1,13 @@ #ifndef __PDBGPROXY_H #define __PDBGPROXY_H -enum gdb_command {NONE, GET_GPRS, GET_SPR, GET_MEM, - STOP_REASON, GET_THREAD, SET_THREAD, V_CONTC, V_CONTS, - PUT_MEM, INTERRUPT, DETACH, LAST_CMD}; +enum gdb_command {NONE, GET_GPRS, GET_SPR, + STOP_REASON, GET_THREAD, SET_THREAD, + V_CONTC, V_CONTS, + QF_THREADINFO, QS_THREADINFO, + GET_MEM, PUT_MEM, + INTERRUPT, DETACH, LAST_CMD}; + typedef void (*command_cb)(uint64_t *stack, void *priv); void parser_init(command_cb *callbacks);
This implements the threadinfo gdb commands, and removes the restriction of a single target. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- README.md | 17 +- src/gdb_parser.rl | 16 +- src/gdb_parser_precompile.c | 328 +++++++++++++++++++----------------- src/pdbgproxy.c | 66 +++++++- src/pdbgproxy.h | 10 +- 5 files changed, 267 insertions(+), 170 deletions(-)