Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Matthieu Longo <matthieu.longo@arm.com>
To: "Joos, Christina" <christina.joos@intel.com>,
	"gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
Cc: Luis Machado <luis.machado@amd.com>,
	Luis Machado <luis.machado.foss@gmail.com>,
	Thiago Jung Bauermann <thiago.bauermann@linaro.org>,
	Simon Marchi <simark@simark.ca>,
	Kevin Buettner <kevinb@redhat.com>
Subject: Re: [PATCH v1 3/6] gdb: introduce helper class file_reader_t
Date: Mon, 24 Aug 2026 17:30:14 +0100	[thread overview]
Message-ID: <a16a2a48-0cb4-4656-b9ed-88dc730ac380@arm.com> (raw)
In-Reply-To: <2c974a80-9ad6-4b46-a6a9-33a8e710d372@arm.com>

On 14/08/2026 16:25, Matthieu Longo wrote:
> On 10/08/2026 14:07, Joos, Christina wrote:
>> Hi Matthieu,
>>
>> Please find my feedback below.
>>
>>> -----Original Message-----
>>> From: Matthieu Longo <matthieu.longo@arm.com>
>>> Sent: Dienstag, 28. Juli 2026 17:17
>>> To: gdb-patches@sourceware.org
>>> Cc: Luis Machado <luis.machado@amd.com>; Luis Machado
>>> <luis.machado.foss@gmail.com>; Thiago Jung Bauermann
>>> <thiago.bauermann@linaro.org>; Simon Marchi <simark@simark.ca>; Kevin
>>> Buettner <kevinb@redhat.com>; Joos, Christina <christina.joos@intel.com>;
>>> Joos, Christina <christina.joos@intel.com>; Matthieu Longo
>>> <matthieu.longo@arm.com>
>>> Subject: [PATCH v1 3/6] gdb: introduce helper class file_reader_t
>>>
>>> Wrap all the boilerplate code required to read a file in a new helper
>>> class: file_reader_t. The class owns the file contents together with the file path,
>>> and provides convenient accessors for the data, size and typed views. It
>>> supports both null-terminated text files and binary files.
>>>
>>> This helper eliminates repeated calls to target_fileio_read_stralloc and
>>> target_fileio_read_alloc, remove explicit memory management with
>>> gdb::unique_xmalloc_ptr, and simplifies the casting logic when working with
>>> binary data.
>>>
>>> The patch converts some of the existing Linux, AMD64, and SPARC code that
>>> reads files from /proc to use file_reader_t.
>>> ---
>>>  gdb/amd64-linux-tdep.c |  12 ++---
>>>  gdb/linux-tdep.c       | 109 ++++++++++++++++++-----------------------
>>>  gdb/sparc64-tdep.c     |  13 +++--
>>>  gdb/target.h           |  79 +++++++++++++++++++++++++++++
>>>  4 files changed, 137 insertions(+), 76 deletions(-)
>>>
>>> diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index
>>> 9bdcc55a0e1..11f0a6952ea 100644
>>> --- a/gdb/linux-tdep.c
>>> +++ b/gdb/linux-tdep.c
>>> @@ -1698,6 +1698,12 @@ parse_smaps_data (const char *data,
>>>    return smaps;
>>>  }
>>>
>>> +static std::vector<struct smaps_data>
>>
>> Nit: we should omit the struct keyword here.
>>
> 
> Fixed. And in others places where it is relevant.
> 
>>> +parse_smaps_data (const file_reader_t<char> &freader) {
>>> +  return parse_smaps_data (freader.data (), freader.filepath ()); }
>>> +
>>>  /* Helper that checks if an address is in a memory tag page for a live
>>>     process.  */
>>>
>>> @@ -1709,17 +1715,13 @@ linux_process_address_in_memtag_page
>>> (CORE_ADDR address)
>>>
>>>    ptid_t ptid = get_process_reference_ptid ();
>>>
>>> -  std::string smaps_file = string_printf ("/proc/%ld/smaps", ptid.lwp ());
>>> -
>>> -  gdb::unique_xmalloc_ptr<char> data
>>> -    = target_fileio_read_stralloc (NULL, smaps_file.c_str ());
>>> -
>>> -  if (data == nullptr)
>>> +  file_reader_t<char> smaps_freader
>>> +    (string_printf ("/proc/%ld/smaps", ptid.lwp ()));  if
>>> + (!smaps_freader)
>>>      return false;
>>>
>>>    /* Parse the contents of smaps into a vector.  */
>>> -  std::vector<struct smaps_data> smaps
>>> -    = parse_smaps_data (data.get (), smaps_file);
>>> +  std::vector<struct smaps_data> smaps = parse_smaps_data
>>> + (smaps_freader);
>>
>> Like amd64_linux_lam_untag_mask we have a minor behavioural change here.
>> But I again see it as an improvement, as the result should be the same, we just
>> return earlier. There might be some more cases in linux-tdep.c, but I did not check
>> all of them.
>>
>> I think it's worth pointing out in the commit message.
>>
> 
> Amended this paragraph in the commit message:
> 
> The patch converts some of the existing Linux, AMD64, and SPARC code that
> reads files from /proc to use file_reader_t. As a side effect,
> amd64_linux_lam_untag_mask and linux_process_address_in_memtag_page
> may now return earlier in case the file is empty.
> 
>>> diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c index
>>> 93db3417a2a..955631b87df 100644
>>> --- a/gdb/sparc64-tdep.c
>>> +++ b/gdb/sparc64-tdep.c
>>> @@ -301,18 +301,16 @@ adi_tag_fd ()
>>>  static bool
>>>  adi_is_addr_mapped (CORE_ADDR vaddr, size_t cnt)  {
>>> -  char filename[MAX_PROC_NAME_SIZE];
>>>    size_t i = 0;
>>>
>>>    pid_t pid = inferior_ptid.pid ();
>>> -  snprintf (filename, sizeof filename, "/proc/%ld/adi/maps", (long) pid);
>>> -  gdb::unique_xmalloc_ptr<char> data
>>> -    = target_fileio_read_stralloc (NULL, filename);
>>> -  if (data)
>>> +  file_reader_t<char> adi_maps_freader
>>> +    (string_printf ("/proc/%d/adi/maps", pid));  if
>>> + (adi_maps_freader.error ())
>>
>> Didn't you mean 
>>   if (!adi_maps_freader.error ())
>>
>> ?
>>
> 
> Yes, you're right.
> 
> However, I am wondering why the diagnostic message is not an error instead of warning.
> Any idea ?
> 
> I would also like to change the program flow to something like:
> 
>   file_reader_t<char> adi_maps_freader
>     (string_printf ("/proc/%d/adi/maps", pid));
>   if (adi_maps_freader)
>     {
>       // This is skipped when the file is empty
>       ...
>     }
>   else if (adi_maps_freader.error ())
>     error (_("unable to open /proc file '%s'"),
> 	     adi_maps_freader.c_filepath ());
>   return false;
> 
>>> diff --git a/gdb/target.h b/gdb/target.h index 819279c08fc..09830dfe3a9
>>> 100644
>>> --- a/gdb/target.h
>>> +++ b/gdb/target.h
>>> @@ -2341,6 +2341,85 @@ extern LONGEST target_fileio_read_alloc (struct
>>> inferior *inf,  extern gdb::unique_xmalloc_ptr<char> target_fileio_read_stralloc
>>>      (struct inferior *inf, const char *filename, LONGEST *len = nullptr);
>>>
>>> +/* Helper class for reading the content of a file on the target.  */
>>> +template <typename T> class file_reader_t {
>>> +  /* The filepath of the file being read.  */
>>> +  std::string m_filepath;
>>> +  /* Smart pointer to the data.  */
>>> +  gdb::unique_xmalloc_ptr<T> m_data;
>>> +  /* Number of bytes read.  */
>>> +  LONGEST m_size;
>>> +
>>> +public:
>>> +  file_reader_t (const std::string &filepath)
>>> +    : m_filepath (filepath)
>>> +    , m_size (0)
>>> +  {
>>> +    if constexpr (std::is_same_v<T, char>)
>>> +      m_data = target_fileio_read_stralloc (nullptr, m_filepath.c_str (),
>>> +					    &m_size);
>>> +    else
>>> +      {
>>> +	gdb_byte *buf = nullptr;
>>> +	m_size = target_fileio_read_alloc (nullptr, m_filepath.c_str (), &buf);
>>> +	m_data = gdb::unique_xmalloc_ptr<T> (reinterpret_cast<T *>(buf));
>>> +      }
>>> +  }
>>> +
>>> +  file_reader_t (file_reader_t &&other)
>>> +    : m_filepath (std::move (other.m_filepath))
>>> +    , m_data (std::move (other.m_data))
>>> +    , m_size (other.m_size)
>>> +  {}
>>
>> I hope I get the C++ rules right here:
>> AFAIK, since we have the move constructor, we implicitly delete the copy
>> constructor and the copy assignment operator.
>>
>> Wouldn't it be clearer if we'd write this explicitly using DISABLE_COPY_AND_ASSIGN ?
>>
> 
> I agree. Added.
> 
>> I also wondered if the default move constructor is doing the same thing, so we could write sth. like:
>> file_reader_t (file_reader_t &&other) = default;
>>
>> instead.
>>
> 
> Fixed as follows:
> 
>   file_reader_t (file_reader_t &&) = default;
>   file_reader_t &operator= (file_reader_t &&) = default;
> 
>   DISABLE_COPY_AND_ASSIGN (file_reader_t);
> 
>>> +  /* Return true if the file was read successfully but contained no
>>> + data.  */  bool empty () const noexcept  { return m_data != nullptr &&
>>> + m_size == 0; }
>>> +
>>> +  /* Return true if the file could not be read.  */  bool error ()
>>> + const noexcept  { return m_data == nullptr || m_size < 0; }
>>> +  /* Return true if the file was read successfully and is non-empty.
>>> + */  explicit operator bool () const noexcept  { return !(error () ||
>>> + empty ()); }
>>
>> To me it would feel more natural if we return true also in case the file is empty.
>> Then we could also omit the error function.
>>
>> But I don't have a very strong opinion about this.
>>
>>
>> Christina
> 
> The cases where we use .error (), the alternative should check whether the file is not empty. From
> this perspective, including !.empty () in the boolean operator makes sense.
> 
> See for instance linux_vsyscall_range_raw or adi_is_addr_mapped, the loop with strtok_r() will be
> skipped if the content is empty.
> 
> Matthieu

Hi Christina,

Do you have further comments ?
I would like to publish a v2.

Regards,
Matthieu

  reply	other threads:[~2026-08-24 16:31 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-28 15:16 [PATCH v1 0/6] gdb: introduce file_reader_t to read procfs files Matthieu Longo
2026-07-28 15:16 ` [PATCH v1 1/6] target_fileio_read_stralloc: add an optional length parameter Matthieu Longo
2026-08-03  4:49   ` Thiago Jung Bauermann
2026-07-28 15:16 ` [PATCH v1 2/6] gdb support: add gdb::ranges::replace algorithm Matthieu Longo
2026-07-28 15:16 ` [PATCH v1 3/6] gdb: introduce helper class file_reader_t Matthieu Longo
2026-08-03  5:00   ` Thiago Jung Bauermann
2026-08-10 13:07   ` Joos, Christina
2026-08-14 15:25     ` Matthieu Longo
2026-08-24 16:30       ` Matthieu Longo [this message]
2026-08-25  8:55       ` Joos, Christina
2026-07-28 15:16 ` [PATCH v1 4/6] gdb/linux-tdep: migrate linux_info_proc to file_reader_t Matthieu Longo
2026-08-03  5:00   ` Thiago Jung Bauermann
2026-07-28 15:16 ` [PATCH v1 5/6] gdb/linux-tdep: migrate linux_find_memory_regions_full " Matthieu Longo
2026-08-03  5:01   ` Thiago Jung Bauermann
2026-07-28 15:17 ` [PATCH v1 6/6] gdb/linux-tdep: remove legacy parse_smaps_data overload Matthieu Longo
2026-07-28 15:43 ` [PATCH v1 0/6] gdb: introduce file_reader_t to read procfs files Joos, Christina

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=a16a2a48-0cb4-4656-b9ed-88dc730ac380@arm.com \
    --to=matthieu.longo@arm.com \
    --cc=christina.joos@intel.com \
    --cc=gdb-patches@sourceware.org \
    --cc=kevinb@redhat.com \
    --cc=luis.machado.foss@gmail.com \
    --cc=luis.machado@amd.com \
    --cc=simark@simark.ca \
    --cc=thiago.bauermann@linaro.org \
    /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