From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
To: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Cc: gdb-patches@sourceware.org, Markus Metzger <markus.t.metzger@intel.com>
Subject: Re: [PATCH v2 11/47] gdb, gdbserver, rsp, ze: acknowledge libraries
Date: Wed, 16 Jul 2025 01:20:01 -0300 [thread overview]
Message-ID: <87y0sodaxa.fsf@linaro.org> (raw)
In-Reply-To: <20241213-upstream-intelgt-mvp-v2-11-5c4caeb7b33d@intel.com> (Tankut Baris Aktemur's message of "Fri, 13 Dec 2024 16:59:28 +0100")
Hello Baris,
Tankut Baris Aktemur <tankut.baris.aktemur@intel.com> writes:
> @@ -48084,16 +48141,18 @@ The format of a library list is described by this DTD:
> @smallexample
> <!-- library-list: Root element with versioning -->
> <!ELEMENT library-list (library | in-memory-library)*>
> -<!ATTLIST library-list version CDATA #FIXED "1.1">
> +<!ATTLIST library-list version CDATA #FIXED "1.2">
> <!ELEMENT library (segment*, section*)>
> -<!ATTLIST library name CDATA #REQUIRED>
> +<!ATTLIST library name CDATA #REQUIRED
> + ack (yes | no) 'no'>
> <!ELEMENT in-memory-library (segment*, section*)>
> -<!ATTLIST in-memory-library begin CDATA #REQUIRED
> - end CDATA #REQUIRED>
> +<!ATTLIST in-memory-library begin CDATA #REQUIRED
> + end CDATA #REQUIRED
> + ack (yes | no) 'no'>
> <!ELEMENT segment EMPTY>
> -<!ATTLIST segment address CDATA #REQUIRED>
> +<!ATTLIST segment address CDATA #REQUIRED>
> <!ELEMENT section EMPTY>
> -<!ATTLIST section address CDATA #REQUIRED>
> +<!ATTLIST section address CDATA #REQUIRED>
> @end smallexample
I would move the last column (the one with "#FIXED", "#REQUIRED" and
'no') a couple more spaces to the right. The change above leaves them
right next to "(segment*, section*)>" and it feels a bit crowded IMHO.
>
> In addition, segments and section descriptors cannot be mixed within a
> diff --git a/gdb/features/library-list.dtd b/gdb/features/library-list.dtd
> index f55071c8e906f091752e8ca78ec29bcd76028433..473b8eaa719b1d310f9eb4fe8f531df85008845d 100644
> --- a/gdb/features/library-list.dtd
> +++ b/gdb/features/library-list.dtd
> @@ -6,14 +6,16 @@
>
> <!-- library-list: Root element with versioning -->
> <!ELEMENT library-list (library | in-memory-library)*>
> -<!ATTLIST library-list version CDATA #FIXED "1.1">
> +<!ATTLIST library-list version CDATA #FIXED "1.2">
Same comment here as in patch 10: IMO it's better to just use CDATA
#REQUIRED and rely on library_list_start_list to check if the version is
acceptable.
Also, same comment about bumping the version only once in the series, to
1.1.
>
> <!ELEMENT library (segment*, section*)>
> -<!ATTLIST library name CDATA #REQUIRED>
> +<!ATTLIST library name CDATA #REQUIRED
> + ack (yes | no) 'no'>
>
> <!ELEMENT in-memory-library (segment*, section*)>
> -<!ATTLIST in-memory-library begin CDATA #REQUIRED
> - end CDATA #REQUIRED>
> +<!ATTLIST in-memory-library begin CDATA #REQUIRED
> + end CDATA #REQUIRED
> + ack (yes | no) 'no'>
>
> <!ELEMENT segment EMPTY>
> <!ATTLIST segment address CDATA #REQUIRED>
Same comment here about moving the last column a couple of spaces to the
right.
<snip>
> @@ -15679,6 +15700,60 @@ remote_target::vcont_r_supported ()
> && get_remote_state ()->supports_vCont.r);
> }
>
> +void
> +remote_target::ack_library (const char *name)
Missing doc comment for this method.
> +{
> + struct remote_state *rs = get_remote_state ();
No need for the struct keyword.
> + char *p = rs->buf.data ();
> + char *endp = p + get_remote_packet_size ();
> +
> + xsnprintf (p, endp - p, "vAck:library:%s", name);
> +
> + putpkt (rs->buf);
> + getpkt (&rs->buf, 0);
> +
> + packet_result result
> + = m_features.packet_ok (rs->buf, PACKET_vAck_library);
This fits 80 columns as one line.
> + switch (result.status ())
> + {
> + case PACKET_OK:
> + break;
> + case PACKET_UNKNOWN:
> + error (_("No support for acknowledging libraries."));
> + case PACKET_ERROR:
> + error (_("Acknowledging library '%s' failed: '%s'"), name,
> + rs->buf.data ());
> + }
> +}
> +
> +void
> +remote_target::ack_in_memory_library (CORE_ADDR begin, CORE_ADDR end)
Missing doc comment for this method.
> +{
> + struct remote_state *rs = get_remote_state ();
No need for the struct keyword.
> + char *p = rs->buf.data ();
> + char *endp = p + get_remote_packet_size ();
> +
> + xsnprintf (p, endp - p, "vAck:in-memory-library:%s,%s",
> + core_addr_to_string_nz (begin), core_addr_to_string_nz (end));
> +
> + putpkt (rs->buf);
> + getpkt (&rs->buf, 0);
> +
> + packet_result result
> + = m_features.packet_ok (rs->buf, PACKET_vAck_in_memory_library);
> + switch (result.status ())
> + {
> + case PACKET_OK:
> + break;
> + case PACKET_UNKNOWN:
> + error (_("No support for acknowledging in-memory libraries."));
> + case PACKET_ERROR:
> + error (_("Failed to acknowledge in-memory library %s-%s: %s"),
> + core_addr_to_string_nz (begin), core_addr_to_string_nz (end),
> + rs->buf.data ());
> + }
> +}
> +
> /* The "set/show range-stepping" set hook. */
>
> static void
> @@ -16442,6 +16517,12 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
>
> add_packet_config_cmd (PACKET_vCtrlC, "vCtrlC", "ctrl-c", 0);
>
> + add_packet_config_cmd (PACKET_vAck_library,
> + "vAck:library", "ack-library", 0);
This fits 80 columns as one line.
> +
> + add_packet_config_cmd (PACKET_vAck_in_memory_library,
> + "vAck:in-memory-library", "ack-in-memory-library", 0);
> +
> add_packet_config_cmd (PACKET_QThreadEvents, "QThreadEvents", "thread-events",
> 0);
<snip>
> @@ -473,6 +503,32 @@ solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
> return in_plt_section (pc);
> }
>
> +static void
> +solib_target_ack_library (solib &so)
> +{
> + lm_info_target *lm
> + = gdb::checked_static_cast<lm_info_target *> (so.lm_info.get ());
> +
> + if (!lm->need_ack)
> + return;
> +
> + /* Try only once, whether we succeed or not. */
> + lm->need_ack = false;
> + switch (lm->location)
> + {
> + case lm_on_disk:
> + target_ack_library (so.so_original_name.c_str ());
> + return;
> +
> + case lm_in_memory:
> + target_ack_in_memory_library (lm->begin, lm->end);
> + return;
> + }
> +
> + warning (_("bad solib location '%d' for %s."), lm->location,
> + so.so_original_name.c_str ());
Isn't this an internal error? If so, it should call
gdb_assert_not_reached.
> +}
> +
> const solib_ops solib_target_so_ops =
> {
> solib_target_relocate_section_addresses,
> @@ -489,4 +545,5 @@ const solib_ops solib_target_so_ops =
> nullptr,
> default_find_solib_addr,
> gdb_bfd_open_from_target_memory,
> + solib_target_ack_library,
> };
> diff --git a/gdb/solib.c b/gdb/solib.c
> index cb302f9215257ddff18c94f5be39e189b02d84e6..92fc5137a3d469f55043235a65dcadcc1f25fe96 100644
> --- a/gdb/solib.c
> +++ b/gdb/solib.c
> @@ -967,6 +967,7 @@ solib_add (const char *pattern, int from_tty, int readsyms)
> if (from_tty)
> add_flags |= SYMFILE_VERBOSE;
>
> + std::list<solib *> added_solibs;
> for (solib &gdb : current_program_space->solibs ())
> if (!pattern || re_exec (gdb.so_name.c_str ()))
> {
> @@ -989,14 +990,23 @@ solib_add (const char *pattern, int from_tty, int readsyms)
> styled_string (file_name_style.style (),
> gdb.so_name.c_str ()));
> }
> - else if (solib_read_symbols (gdb, add_flags))
> - loaded_any_symbols = true;
> + else
> + added_solibs.emplace_back (&gdb);
This should use the push_back method since we don't want to create a new
object in the list.
> }
> }
>
> + for (solib *gdb : added_solibs)
> + if (solib_read_symbols (*gdb, add_flags))
> + loaded_any_symbols = true;
> +
> if (loaded_any_symbols)
> breakpoint_re_set ();
>
> + /* Acknowledge loading of new solibs. This must be called after
> + breakpoints have been set in this newly loaded solib. */
> + for (solib *gdb : added_solibs)
> + solib_ack_library (*gdb);
> +
> if (from_tty && pattern && !any_matches)
> gdb_printf ("No loaded shared libraries match the pattern `%s'.\n",
> pattern);
> @@ -1700,6 +1710,16 @@ default_find_solib_addr (solib &so)
> return {};
> }
>
> +/* See solist.h. */
> +
> +void solib_ack_library (solib &so)
This function is only called from solib_add, shouldn't it be static?
Or even just inlined into the caller?
> +{
> + const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
> +
> + if (ops->ack_library != nullptr)
> + (*ops->ack_library) (so);
> +}
> +
> void _initialize_solib ();
>
> void
<snip>
> @@ -60,6 +72,78 @@ unloaded_dll (const char *name, CORE_ADDR base_addr)
> unloaded_dll (current_process (), name, base_addr);
> }
>
> +static void
> +ack_dll (process_info *process, dll_info &dll)
> +{
> + gdb_assert (dll.need_ack);
> +
> + switch (dll.location)
> + {
> + case dll_info::on_disk:
> + /* Check if this is a temporary file for an in-memory library. */
> + if (dll.begin == UNSPECIFIED_CORE_ADDR)
> + {
> + target_ack_library (process, dll.name.c_str ());
> + dll.need_ack = false;
> + return;
> + }
> +
> + [[fallthrough]];
> + case dll_info::in_memory:
> + target_ack_in_memory_library (process, dll.begin, dll.end);
> + dll.need_ack = false;
> + return;
> + }
I'm confused by this switch statement. So a vAck:library packet will be
used only if it's for an in-memory library and vAck:in-memory-library
isn't supported? I would think that a vAck:library would also be used
for an on-disk library.
> + internal_error (_("bad library location: %d."), dll.location);
> +}
> +
> +void
> +ack_dll (process_info *proc, const char *name)
> +{
> + std::list<dll_info> &dlls = proc->all_dlls;
> + std::list<dll_info>::iterator it
> + = std::find_if (dlls.begin (), dlls.end (),
> + [name] (const dll_info &dll)
> + {
> + return (dll.name == std::string (name));
> + });
> +
> + if (it != dlls.end ())
> + ack_dll (proc, *it);
> +}
> +
> +void
> +ack_dll (const char *name)
> +{
> + ack_dll (current_process (), name);
> +}
> +
> +void
> +ack_dll (process_info *proc, CORE_ADDR begin, CORE_ADDR end)
> +{
> + std::list<dll_info> &dlls = proc->all_dlls;
> + std::list<dll_info>::iterator it
> + = std::find_if (dlls.begin (), dlls.end (),
> + [begin, end] (const dll_info &dll)
> + {
> + /* For root devices with multiple sub-devices, modules with
> + identical start/end addresses may be received for different
> + sub-devices. Therefore we check for the 'NEED_ACK' flag in
> + the search, too. */
And is it guaranteed that only one of them will have need_ack set to
true? Can you explain that in the comment?
> + return ((dll.begin == begin) && (dll.end == end) && dll.need_ack);
> + });
> +
> + if (it != dlls.end ())
> + ack_dll (proc, *it);
> +}
<snip>
> @@ -3371,6 +3398,66 @@ err:
> return;
> }
>
> +/* Parse vAck packets. */
> +
> +static void
> +handle_v_ack (char *own_buf)
> +{
> + client_state &cs = get_client_state ();
> + char *p;
> +
> + /* Move past vAck: to the first type string. */
> + p = &own_buf[5];
> + do
> + {
> + if (cs.vack_library_supported
> + && (strncmp (p, "library:", strlen ("library:")) == 0))
> + {
> + p += strlen ("library:");
> +
> + /* We expect a single argument: the filename. */
> + const char *name = p;
> + p = strchr (p, ';');
> + if (p != nullptr)
> + *p++ = '\0';
> +
> + ack_dll (name);
The documentation for vAck says:
Acknowledge a ‘;’-separated list of remote stub responses, each with a
‘,’- separated list of arguments defined by its type.
But the above will consider everything between the ':' and ';' to be the
library name, even if there's a ','. I think you should check whether
there's a ',' in name, and if so either reject the packet or ignore the
additional arguments — not sure which is better, I'm leaning towards
rejecting the packet.
> + }
> + else if (cs.vack_in_memory_library_supported
> + && (strncmp (p, "in-memory-library:",
> + strlen ("in-memory-library:")) == 0))
> + {
> + p += strlen ("in-memory-library:");
> +
> + /* We expect two arguments: begin and end address. */
> + CORE_ADDR begin, end;
> +
> + begin = (CORE_ADDR) strtoull (p, &p, 16);
> + if (*p != ',')
> + break;
If this break is taken and begin is the last argument in the packet,
then won't *p == 0 and cause write_ok () to be called below? An error
should be returned instead.
> + end = (CORE_ADDR) strtoull (p+1, &p, 16);
> + if (*p == ';')
> + p += 1;
> + else if (*p != 0)
> + break;
> +
> + ack_dll (begin, end);
> + }
> + else
> + break;
> + }
> + while (p != nullptr && *p != 0);
> +
> + if (p == nullptr || *p == 0)
> + write_ok (own_buf);
> + else
> + {
> + std::string junk { p };
> + sprintf (own_buf, "E.junk in vAck: '%s'.", junk.c_str ());
> + }
> +}
--
Thiago
next prev parent reply other threads:[~2025-07-16 4:20 UTC|newest]
Thread overview: 87+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-13 15:59 [PATCH v2 00/47] A new target to debug Intel GPUs Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 01/47] gdb, intelgt: add intelgt as a basic machine Tankut Baris Aktemur
2024-12-16 7:53 ` Jan Beulich
2024-12-17 18:48 ` Aktemur, Tankut Baris
2024-12-18 7:19 ` Jan Beulich
2024-12-20 9:55 ` Aktemur, Tankut Baris
2025-02-03 17:17 ` Aktemur, Tankut Baris
2025-02-04 7:06 ` Jan Beulich
2024-12-13 15:59 ` [PATCH v2 02/47] bfd: add intelgt target to BFD Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 03/47] ld: add intelgt as a target configuration Tankut Baris Aktemur
2024-12-16 7:43 ` Jan Beulich
2024-12-13 15:59 ` [PATCH v2 04/47] opcodes: add intelgt as a configuration Tankut Baris Aktemur
2024-12-16 7:44 ` Jan Beulich
2024-12-17 18:47 ` Aktemur, Tankut Baris
2024-12-18 7:22 ` Jan Beulich
2024-12-20 9:47 ` Aktemur, Tankut Baris
2025-01-03 4:46 ` Simon Marchi
2025-02-03 17:13 ` Aktemur, Tankut Baris
2025-02-04 7:07 ` Jan Beulich
2024-12-13 15:59 ` [PATCH v2 05/47] gdb, arch, intelgt: add intelgt arch definitions Tankut Baris Aktemur
2025-07-08 3:03 ` Thiago Jung Bauermann
2025-07-21 10:49 ` Aktemur, Tankut Baris
2024-12-13 15:59 ` [PATCH v2 06/47] gdb, intelgt: add the target-dependent definitions for the Intel GT architecture Tankut Baris Aktemur
2025-07-08 2:43 ` Thiago Jung Bauermann
2025-07-18 17:43 ` Aktemur, Tankut Baris
2024-12-13 15:59 ` [PATCH v2 07/47] gdb, gdbserver, gdbsupport: add 'device' tag to XML target description Tankut Baris Aktemur
2024-12-13 16:45 ` Eli Zaretskii
2025-07-08 4:04 ` Thiago Jung Bauermann
2025-07-21 10:49 ` Aktemur, Tankut Baris
2024-12-13 15:59 ` [PATCH v2 08/47] gdb, intelgt: add disassemble feature for the Intel GT architecture Tankut Baris Aktemur
2025-07-09 3:12 ` Thiago Jung Bauermann
2024-12-13 15:59 ` [PATCH v2 09/47] gdbsupport, filestuff, ze: temporary files Tankut Baris Aktemur
2025-07-14 1:26 ` Thiago Jung Bauermann
2024-12-13 15:59 ` [PATCH v2 10/47] gdb, gdbserver, ze: in-memory libraries Tankut Baris Aktemur
2025-07-14 2:35 ` Thiago Jung Bauermann
2025-07-31 6:09 ` Metzger, Markus T
2025-07-16 4:08 ` Thiago Jung Bauermann
2024-12-13 15:59 ` [PATCH v2 11/47] gdb, gdbserver, rsp, ze: acknowledge libraries Tankut Baris Aktemur
2024-12-13 16:43 ` Eli Zaretskii
2025-07-16 4:20 ` Thiago Jung Bauermann [this message]
2025-07-31 6:09 ` Metzger, Markus T
2024-12-13 15:59 ` [PATCH v2 12/47] gdb, solib, ze: solib_bfd_open_from_target_memory Tankut Baris Aktemur
2025-07-18 0:42 ` Thiago Jung Bauermann
2024-12-13 15:59 ` [PATCH v2 13/47] gdb, remote, ze: fix "$Hc-1#09...Packet received: E01" during startup Tankut Baris Aktemur
2025-07-18 0:41 ` Thiago Jung Bauermann
2025-08-01 7:55 ` Metzger, Markus T
2024-12-13 15:59 ` [PATCH v2 14/47] gdb, infrun, ze: allow saving process events Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 15/47] gdb, ze: add TARGET_WAITKIND_UNAVAILABLE Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 16/47] gdb, infrun, ze: handle stopping unavailable threads Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 17/47] gdb, infrun, ze: allow resuming " Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 18/47] gdb, gdbserver, ze: add U stop reply Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 19/47] gdb, gdbserver, ze: add library notification to " Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 20/47] gdbserver, ze: report TARGET_WAITKIND_UNAVAILABLE events Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 21/47] gdb, ze: handle TARGET_WAITKIND_UNAVAILABLE in stop_all_threads Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 22/47] gdb, remote: handle thread unavailability in print_one_stopped_thread Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 23/47] gdb, remote: do 'remote_add_inferior' in 'remote_notice_new_inferior' earlier Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 24/47] gdb, remote: handle a generic process PID in remote_notice_new_inferior Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 25/47] gdb, remote: handle a generic process PID in process_stop_reply Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 26/47] gdb: use the pid from inferior in setup_inferior Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 27/47] gdb: revise the pid_to_exec_file target op Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 28/47] gdb: load solibs if the target does not have the notion of an exec file Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 29/47] gdbserver: import AC_LIB_HAVE_LINKFLAGS macro into the autoconf script Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 30/47] gdbserver: add a pointer to the owner thread in regcache Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 31/47] gdbserver: dump 'xx...x' in collect_register_as_string for unavailable register Tankut Baris Aktemur
2024-12-23 11:38 ` Aktemur, Tankut Baris
2024-12-23 13:47 ` Luis Machado
2024-12-13 15:59 ` [PATCH v2 32/47] gdbserver: wait for stopped threads in queue_stop_reply_callback Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 33/47] gdbserver: adjust pid after the target attaches Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 34/47] gdb: do not create a thread after a process event Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 35/47] gdb, ze: on a whole process stop, mark all threads as not_resumed Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 36/47] gdb, dwarf, ze: add DW_OP_INTEL_regval_bits Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 37/47] gdbserver: allow configuring for a heterogeneous target Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 38/47] gdbserver, ze, intelgt: introduce ze-low and intel-ze-low targets Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 39/47] testsuite, sycl: add SYCL support Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 40/47] testsuite, sycl: add test for backtracing inside a kernel Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 41/47] testsuite, sycl: add test for 'info locals' and 'info args' Tankut Baris Aktemur
2024-12-13 15:59 ` [PATCH v2 42/47] testsuite, sycl: add tests for stepping and accessing data elements Tankut Baris Aktemur
2024-12-13 16:00 ` [PATCH v2 43/47] testsuite, sycl: add test for 1-D and 2-D parallel_for kernels Tankut Baris Aktemur
2024-12-13 16:00 ` [PATCH v2 44/47] testsuite, sycl: add test for scheduler-locking Tankut Baris Aktemur
2024-12-13 16:00 ` [PATCH v2 45/47] testsuite, arch, intelgt: add a disassembly test Tankut Baris Aktemur
2024-12-13 16:00 ` [PATCH v2 46/47] testsuite, arch, intelgt: add intelgt-program-bp.exp Tankut Baris Aktemur
2024-12-13 16:00 ` [PATCH v2 47/47] testsuite, sycl: test canceling a stepping flow Tankut Baris Aktemur
2025-02-07 10:18 ` [PATCH v2 00/47] A new target to debug Intel GPUs Aktemur, Tankut Baris
2025-05-08 7:40 ` Aktemur, Tankut Baris
2025-05-26 8:03 ` Aktemur, Tankut Baris
2025-06-17 12:22 ` Aktemur, Tankut Baris
2025-07-03 12:55 ` Aktemur, Tankut Baris
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87y0sodaxa.fsf@linaro.org \
--to=thiago.bauermann@linaro.org \
--cc=gdb-patches@sourceware.org \
--cc=markus.t.metzger@intel.com \
--cc=tankut.baris.aktemur@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox