Bug 95722 - libatomic crashes on __atomic_load of const object
Summary: libatomic crashes on __atomic_load of const object
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 10.1.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-06-17 14:55 UTC by Luís Marques
Modified: 2020-06-18 16:16 UTC (History)
3 users (show)

See Also:
Host:
Target: x86_64
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Luís Marques 2020-06-17 14:55:10 UTC
With this code in `test.c`:

```
struct S {
    int x;
    int y;
    int z;
};

int main() {
    __attribute__((aligned(16))) static const _Atomic struct S a;
    struct S b;
    b = a;
}
```

On x86_64 I get:

```
$ gcc test.c -latomic && ./a.out 
Segmentation fault (core dumped)
```

It crashes on a `lock cmpxchg16b` with the address of `a`, so I imagine the libatomic implementation is dispatching to an optimized __atomic_load case where the code assumes it can get a (mutable) lock from the object itself, and when it tries to acquire that lock it writes to `.rodata`, causing the crash.
Comment 1 James Y Knight 2020-06-17 19:10:37 UTC
The fix would be to have libatomic use a lock instead of the lock-free cmpxchg16b instruction to implement atomic_load. But I think this is impossible without causing incompatibility with older GCCs.

Older versions of GCC (before GCC 7), and Clang to this day, emitted cmpxchg16b inline for a 16-byte atomic load when you compile with -mcx16.

And thus, unfortunately, I think if libatomic switched to a lock now, it would not be compatible with those older programs.
Comment 2 Richard Biener 2020-06-18 08:30:58 UTC
I think _Atomic can be ignored on const qualified objects?  Or maybe should even be ill-formed?
Comment 3 joseph@codesourcery.com 2020-06-18 16:16:23 UTC
See bugs 70490 and 84563 regarding atomic_load of const.

The atomic_load generic function takes a pointer-to-const-atomic argument 
just like any other library function that takes an argument it does not 
modify.  It's certainly valid to do an atomic load through such a pointer 
in a case where the original object was not defined as const but a pointer 
to const was passed to the function doing the load.

The question is whether it is or should be valid in the case where the 
object was defined as const.  If it is, that would constrain code 
sequences used in any case where the compiler cannot see that the object 
definitely isn't in read-only memory, including for other operations that 
might only be valid for writable memory but need to interact correctly 
with atomic_load.