From: Simon Marchi <simon.marchi@polymtl.ca>
To: Lancelot SIX <lsix@lancelotsix.com>, Aaron Merey <amerey@redhat.com>
Cc: gdb-patches@sourceware.org, tom@tromey.com
Subject: Re: [PATCH 2/3] gdb: Add soname to build-id mapping for corefiles
Date: Tue, 17 Aug 2021 09:58:20 -0400 [thread overview]
Message-ID: <6d314528-224a-3e5e-2d4b-070ea776823d@polymtl.ca> (raw)
In-Reply-To: <20210815145147.ap32fq6wji34wjyf@lsix-M11x-R2>
I did not do a full review, since Lancelot's comments were already a
good start. I just added some complements to his comments.
>> /* See arch-utils.h. */
>> void
>> -default_read_core_file_mappings (struct gdbarch *gdbarch,
>> - struct bfd *cbfd,
>> - gdb::function_view<void (ULONGEST count)>
>> - pre_loop_cb,
>> - gdb::function_view<void (int num,
>> - ULONGEST start,
>> - ULONGEST end,
>> - ULONGEST file_ofs,
>> - const char *filename)>
>> - loop_cb)
>> +default_read_core_file_mappings
>> + (struct gdbarch *gdbarch,
>> + struct bfd *cbfd,
>> + gdb::function_view<void (ULONGEST count)> pre_loop_cb,
>> + gdb::function_view<void (int num,
>> + ULONGEST start,
>> + ULONGEST end,
>> + ULONGEST file_ofs,
>> + const char *filename,
>> + const bfd_build_id *build_id)>
>> + loop_cb)
>
> It looks like 'loop_cb' could go on the previous line.
>
> If the type of the function callbacks are too big, I guess it could be
> possible to give them a name before declaring the function. Something
> like
>
> using loop_cb_ftype = gdb::function_view<void (...)>;
Agreed, and giving a name to the function type helps readability too.
>> @@ -282,6 +282,16 @@ core_target::build_file_mappings ()
>>
>> /* Set target_section fields. */
>> m_core_file_mappings.emplace_back (start, end, sec);
>> +
>> + /* If this is a bfd of a shared library, record its soname
>> + and build id. */
>> + if (build_id != nullptr)
>> + {
>> + gdb::optional<std::string> soname = gdb_bfd_read_elf_soname (bfd);
>> + if (soname)
>> + current_program_space->set_cbfd_soname_build_id (soname->data (),
>> + build_id);
>
> Here, since set_cbfd_soname_build_id's first argument is a std::string,
> you could just use '*soname' instead of 'soname->data ()'.
Since the caller (here) doesn't need to keep the string, I would suggest
`std::move (*soname)` (see below).
>> @@ -358,6 +359,41 @@ print_program_space (struct ui_out *uiout, int requested)
>> }
>> }
>>
>> +/* See progspace.h. */
>> +
>> +void
>> +program_space::set_cbfd_soname_build_id (std::string soname,
>
> This parameter could be 'std::string const &' or...
>
>> + const bfd_build_id *build_id)
>> +{
>> + std::string build_id_hex = build_id_to_string (build_id);
>> + cbfd_soname_to_build_id[soname] = build_id_hex;
>
> ... use 'std::move (soname)' here.
>
> I guess the more 'usual' approach would be to have the argument as a
> const reference (but to be honest, the implication of calling one more
> ctor and copying the soname is negligible, to say the least).
Since set_cbfd_soname_build_id needs to keep its own copy of the object,
I think it's better to take it by value like this, and have the caller
std::move its copy if it doesn't need to keep it around. And have
set_cbfd_soname_build_id std::move it into the map:
cbfd_soname_to_build_id[std::move (soname)] = build_id_hex;
This way, soname is never copied if it doesn't need to. Taking by
const-reference means that set_cbfd_soname_build_id will have no choice
but to copy the string into the map.
And in fact, I would suggest doing:
cbfd_soname_to_build_id[std::move (soname)]
= build_id_to_string (build_id);
... to avoid copying the build_id_hex string. Alternatively, you could
do:
std::string build_id_hex = build_id_to_string (build_id);
cbfd_soname_to_build_id[std::move (soname)] = std::move (build_id_hex);
... but I think the first version is fine.
>> +
>> + return;
>
> I am not sure if the GNU coding standard says something about this, but
> 'return;' as the last statement of a void function is redundant.
Indeed.
>> +}
>> +
>> +/* See progspace.h. */
>> +
>> +const char *
>> +program_space::get_cbfd_soname_build_id (const char *soname)
>
> With set_cbfd_soname_build_id using a std::string, I would find it more
> consistent to use std::string here also. Any reason not to use it I
> missed?
>
> You could use 'basename (soname.c_str ())' bellow.
>
> The return type could also be 'const std::string *' (the map stores
> std::string internally), but keeping a const char * is pretty similar.
We wouldn't want to return an std::string, that would make an
unnecessary copy. If returning a `const char *` doesn't make life
difficult for the caller, I think it's perfectly fine. Previously, I
would have suggested returning string_view, because that abstracts how
the string is stored. But that isn't right, since the string_view
interface doesn't require the view to be null-terminated (which we
usually need). We would need something like cstring_view instead:
http://open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1402r0.pdf
But in the mean time, I think `const char *` is fine.
>> +gdb_bfd_read_elf_soname (struct bfd *bfd)
>> +{
>> + gdb_assert (bfd != nullptr);
>> +
>> + gdb_bfd_ref_ptr abfd = gdb_bfd_open (bfd->filename, gnutarget);
>> +
>> + if (abfd == nullptr)
>> + return gdb::optional<std::string> ();
>> +
>> + /* Check that bfd is an ET_DYN ELF file. */
>> + bfd_check_format (abfd.get (), bfd_object);
I asked this in my previous review, still applies here:
What's the point of calling bfd_check_format without checking the
result? It looks like a function without side-effects.
>> + if (!(bfd_get_file_flags (abfd.get ()) & DYNAMIC))
>> + return gdb::optional<std::string> ();
>> +
>> + /* Determine soname of shared library. If found map soname to build-id. */
>> + CORE_ADDR idx;
>> + if (!gdb_bfd_scan_elf_dyntag (DT_SONAME, abfd.get (), &idx, nullptr))
>> + return gdb::optional<std::string> ();
>> +
>> + struct bfd_section *dynstr = bfd_get_section_by_name (abfd.get (), ".dynstr");
>> + if (dynstr == nullptr)
>> + return gdb::optional<std::string> ();
>> +
>> + /* Read the soname from the string table. */
>> + gdb::byte_vector dynstr_buf;
>> + if (!gdb_bfd_get_full_section_contents (abfd.get (), dynstr, &dynstr_buf))
>> + return gdb::optional<std::string> ();
>> +
>> + return gdb::optional<std::string> ((char *)dynstr_buf.data () + idx);
Do we need bounds checking to protect against bad ELF files? What if
DT_SONAME points outside .dynstr's size? And ideally that a
null-terminator is found somewhere between idx and the end of the
section. Otherwise, I could craft a .dynstr section that does not
contain a null terminator, that would make GDB read out of bounds.
> This will not change much, but you could cast to 'const char *' (this
> is the type the std::string constructor expects).
And to shorten things up a bit, you can drop "gdb::optional":
return std::string ((const char *) dynstr_buf.data () + idx);
While at it, instead of returning "gdb::optional<std::string> ()" on
failure, you can simply "return {}".
Simon
next prev parent reply other threads:[~2021-08-17 13:59 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-08-12 4:24 [PATCH v3 0/3] Add debuginfod core file support Aaron Merey
2021-08-12 4:24 ` [PATCH 1/3] gdb/solib: Refactor scan_dyntag Aaron Merey
2021-08-17 13:28 ` Simon Marchi
2021-08-19 2:30 ` Aaron Merey
2021-08-12 4:24 ` [PATCH 2/3] gdb: Add soname to build-id mapping for corefiles Aaron Merey
2021-08-15 14:51 ` Lancelot SIX
2021-08-17 13:58 ` Simon Marchi [this message]
2021-08-19 2:22 ` Aaron Merey
2021-09-29 1:12 ` Aaron Merey
2021-10-18 23:06 ` [PING**2][PATCH " Aaron Merey
2021-11-03 18:12 ` [PING**3][PATCH " Aaron Merey
2021-11-04 1:32 ` [PATCH " Simon Marchi
2021-08-12 4:24 ` [PATCH 3/3] PR gdb/27570: missing support for debuginfod in core_target::build_file_mappings Aaron Merey
2021-09-29 1:13 ` Aaron Merey
2021-10-18 23:05 ` [PING**2][PATCH " Aaron Merey
2021-11-03 18:11 ` [PING**3][PATCH " Aaron Merey
2021-11-04 1:37 ` [PATCH " Simon Marchi
2021-11-10 1:47 [PATCH v4 0/3] Add debuginfod core file support Aaron Merey
2021-11-10 1:47 ` [PATCH 2/3] gdb: Add soname to build-id mapping for corefiles Aaron Merey
2021-11-14 2:36 ` Simon Marchi
2021-11-17 3:24 ` Aaron Merey
2021-11-17 14:17 ` Tom Tromey
2021-11-17 21:16 ` Aaron Merey
2022-01-26 1:40 ` Aaron Merey
2022-02-09 2:31 ` Aaron Merey
2022-02-17 16:01 ` Andrew Burgess
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=6d314528-224a-3e5e-2d4b-070ea776823d@polymtl.ca \
--to=simon.marchi@polymtl.ca \
--cc=amerey@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=lsix@lancelotsix.com \
--cc=tom@tromey.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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).