public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Torbjorn SVENSSON <torbjorn.svensson@foss.st.com>
To: Nick Alcock <nick.alcock@oracle.com>
Cc: <binutils@sourceware.org>, Alan Modra <amodra@gmail.com>,
	Yvan Roux <yvan.roux@foss.st.com>
Subject: Re: [PATCH v3] libctf: ctf_member_next needs to return (ssize_t)-1 on error
Date: Tue, 3 Oct 2023 14:59:57 +0200	[thread overview]
Message-ID: <c131c7ce-216e-779c-503a-f9450833261e@foss.st.com> (raw)
In-Reply-To: <87ttr9l2b1.fsf@esperi.org.uk>

Hello Nick,


On 2023-10-02 12:57, Nick Alcock wrote:
> On 29 Sep 2023, Torbjorn SVENSSON verbalised:
> 
>> On 2023-09-28 18:41, Nick Alcock wrote:
>>> Aha! So this is *not* a problem with functions returning int -- it is
>>> specifically a problem with functions returning *size_t types*.
>>
>> So, I'm not sure if were are talking past each other, but I don't think it's a *size_t type* issue either.
>>
>> As I see it, there are 3 different scenarios.
>>
>> 1. The function returns a signed integral type, then -1 would be fine.
>> Even a simple (int)-1 would work as it would be sign-extended.
> 
> Ack.
> 
>> 2. The function returns an unsigned integral type that is as wide, or
>> wider, than unsigned long. In this case, CTF_ERR will be zero extended
>> and the value will be UINT_something_MAX (the number of binary ones
>> depends on the sizeof(unsigned long)).
> 
> Ack. This is the problem area, because the interface contract for libctf
> specifies (or would if it were written down anywhere) that you can test
> all signed returns for error via < 0 and all unsigned ones (like
> ctf_id_t) via == CTF_ERR, and CTF_ERR... has a cast in it.

I don't think this is true with the current logic in place.
On a signed integral function, it could be either -1 (negative one) or, 
if the data type of the called function is wide enough, CTF_ERR.

> I suppose if we changed CTF_ERR to (uintmax_t)-1 this might work for all
> cases, but a) uintmax_t is an annoying sod that doesn't even extend to
> the largest possible unsigned integral type on all platforms and b) this
> just gives us the same problem from the other side if the unsigned type
> is shorter than uintmax_t (which it almost always would be). What would
> happen to the (unsigned long)-1 the libctf function returned when it was
> promoted? Would it turn into (uintmax_t)-1 consistently, given that the
> type has no sign so sign-extension presumably does not apply? I've tried
> to figure it out from the standard text and I guess fevers and bacterial
> infections are not compatible with reading standardese because I haven't
> worked it out yet :P
> 
> (or maybe you need to be on more serious drugs than I'm on when reading
> it. It might well be that way round!)
> 
>> 3. The function return an unsigned integral type that is narrower than
>> unsigned long. In this case, the cast to unsigned long is wider than
>> the return type and may overflow(?). Is it safe to return something
>> bigger than can be represented in the return type?
> 
> Are there any of those at all? I don't think so. It's possible in theory
> but I don't think we use unsigned int anywhere. I suppose size_t might
> be unsigned int on some platforms, and then this problem might arise.
> 
>> In my mind, I see it as we need 2 different implementations. One that
>> returns a simple -1 and another one that casts it for all unsigned
>> calls, but maybe I'm oversimplifying this.
> 
> I suppose if it was always done *at the return site* so the compiler
> could always see the return type properly, it would always get the cast
> right: my worry is the CTF_ERR at the test site, in the user code we
> cannot affect (except by changing CTF_ERR).

I suppose so, but does it really matter when we cannot do this part? Or 
are you thinking about just having the ctf_set_errno function always 
return -1 (negative one) and let the caller do the automagic conversion? 
If so, I think the idiom with return_value == CTF_ERR is going to fail.

>> To make things easier, I would actually consider just having the
>> assign statement and the return statement inlined (without a macro or
>> inline function) directly where they are supposed to be.
>>
>> Would you be open to removing the ctf_set_errno() function completely
>> and just expand it to where it's called (almost like my v2 patch, but
>> everywhere instead)?
> 
> Well, you could use a macro to make it less gross. All the code
> duplication makes me wince a bit.

How would a macro work for this?

Consider that a function returns a char*, in this case, neither CTF_ERR, 
nor -1 should be returned, but instead NULL. Using a macro would make 
this problematic to differentiate.

A possibility could be to have a macro like:

#define CTF_SET_ERRNO(fp,err) do { fp->ctf_errno = err; } while(0)

but what's the point?
Is it better to write:

if (some_failure_condition)
   {
     CTF_SET_ERRNO(fp, ENOMEM);
     return -1; // or CTF_ERR, NULL, ..., depending on the function
   }

instead of:

if (some_failure_condition)
   {
     fp->ctf_errno = ENOMEM;
     return -1; // or CTF_ERR, NULL, ..., depending on the function
   }


> But more problematic from my perspective is the implications for the
> callers. We're trying to get either -1 or (some type)-1 to the callers
> so they can error-check it in a consistent and not-too-horrifying
> fashion, after all. (We could add a ctf_is_error() function or macro
> that does whatever magic is needed if it's too baroque, but that would
> be my least favourite option because it looks nothing like a
> conditional.)

Adding a ctf_is_error()-function would be one way to go, but it would be 
an API change while all the others I've been talking about is internal 
into the library without actually touching the interface.

>> Alternatively, we could start the discussion on adopting the C11 standard instead, but I fear that this will be a much longer
>> discussion than figuring out what the best approach would be for libctf.
> 
> Agreed, or I'd have proposed it already. Toolchain projects like
> binutils must be conservative, and there are no doubt lots of archaic
> weird but valid targets out there where the bootstrap chain requires
> binutils building before GCC and the system compiler is not C11-capable.
> 
>>> ... sorry, I'm still flailing at it. Maybe the above is helpful? (It's
>>> only a very small change atop what you've already done, I think.)
>>
>> Let me know how you want to handle this. :)
> 
> I think we're still narrowing down the problem, really. -1 is such a
> common error return, it's amazing how hard it is to make it work right :)
> 

So, based on all we have talk about so for, I'm leaning towards just 
having the 2 statements in all places where an error should be returned 
and have the change contained inside the library rather than making 
external changes required.
Then the question is, would the CTF_SET_ERRNO macro have anything to 
add? I.e. should we have it even if it's just setting the field or 
should we set the field directly? Regardless, the return statement needs 
to be kept outside that block.

Please let me know what you think so that we can progress on this topic.
I'm currently blocked by this point for the tool chain that I'm supposed 
to deliver.

Kind regards,
Torbjörn

  reply	other threads:[~2023-10-03 13:00 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-24 11:32 [PATCH] " Torbjörn SVENSSON
2023-08-25  2:22 ` Alan Modra
2023-08-25 16:53   ` [PATCH v2] " Torbjörn SVENSSON
2023-08-30  8:34     ` Torbjorn SVENSSON
2023-08-30  9:39       ` Alan Modra
2023-09-07 12:10         ` Nick Alcock
2023-09-08 12:58           ` Torbjorn SVENSSON
2023-09-12 14:23             ` Nick Alcock
2023-09-12 18:44               ` Torbjorn SVENSSON
2023-09-13  9:57               ` [PATCH v3] " Torbjörn SVENSSON
2023-09-13 18:37                 ` Nick Alcock
2023-09-13 20:20                   ` Torbjorn SVENSSON
2023-09-20 17:44                     ` Torbjorn SVENSSON
2023-09-26 14:51                     ` Nick Alcock
2023-09-26 17:28                       ` [PATCH v4] " Torbjörn SVENSSON
2023-09-26 17:49                       ` [PATCH v3] " Torbjorn SVENSSON
2023-09-28 16:41                         ` Nick Alcock
2023-09-29 12:11                           ` Torbjorn SVENSSON
2023-10-02 10:57                             ` Nick Alcock
2023-10-03 12:59                               ` Torbjorn SVENSSON [this message]
2023-10-03 20:53                                 ` Nick Alcock
2023-10-05  8:39                                   ` [PATCH v5] libctf: Sanitize error types for PR 30836 Torbjörn SVENSSON
2023-10-09 10:27                                     ` Nick Alcock
2023-10-09 14:44                                       ` [PATCH v6] " Torbjörn SVENSSON
2023-10-09 15:11                                         ` [PATCH v7] " Torbjörn SVENSSON
2023-10-11 11:14                                           ` Nick Alcock
2023-10-13 14:01                                           ` [PATCH] libctf: check for problems with error returns Nick Alcock
2023-10-13 18:31                                             ` Torbjorn SVENSSON
2023-10-15 19:18                                               ` Nick Alcock
2023-10-16 12:51                                                 ` [PATCH v8] libctf: Sanitize error types for PR 30836 Torbjörn SVENSSON
2023-10-17 15:15                                                   ` Nick Alcock
2023-10-17 15:35                                                     ` Torbjorn SVENSSON
2023-10-17 18:54                                                       ` [PATCH] libctf: Return CTF_ERR in ctf_type_resolve_unsliced " Torbjörn SVENSSON
2023-10-17 19:40                                                         ` Nick Alcock
2023-10-18  7:40                                                           ` Torbjorn SVENSSON
2023-10-20 17:01                                                             ` Nick Alcock
2023-10-16 13:02                                                 ` [PATCH] libctf: check for problems with error returns Torbjorn SVENSSON
2023-10-17 14:45                                                   ` Nick Alcock
2024-01-30 12:46                                             ` Andreas Schwab
2024-01-30 14:22                                               ` Nick Alcock
2024-01-30 14:27                                                 ` Andreas Schwab
2024-03-09  2:44                                                   ` Sam James
2024-03-11 15:14                                                     ` Nick Alcock
2024-03-12  6:52                                                       ` Sam James

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=c131c7ce-216e-779c-503a-f9450833261e@foss.st.com \
    --to=torbjorn.svensson@foss.st.com \
    --cc=amodra@gmail.com \
    --cc=binutils@sourceware.org \
    --cc=nick.alcock@oracle.com \
    --cc=yvan.roux@foss.st.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).