Skip to content

[compiler-rt] Simplify definition of uptr #106155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

arichardson
Copy link
Member

@arichardson arichardson commented Aug 26, 2024

We can rely on the compiler-provided macro UINTPTR_TYPE for all
non-MSVC compilers. I verified via https://godbolt.org/z/MW9KMjv5f that
this works for MSVC as well as GCC 4.5 Clang 3.0, so that should cover
all supported compilers.

This means we no longer need to explicitly handle new architectures
and as an added bonus also adds support for architectures where
unsigned long long cannot be used to hold pointers (e.g. CHERI).

Created using spr 1.3.6-beta.1
@llvmbot
Copy link
Member

llvmbot commented Aug 26, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Alexander Richardson (arichardson)

Changes

We can rely on the compiler-provided macro UINTPTR_TYPE for all
non-MSVC compilers. I verified via https://godbolt.org/z/MW9KMjv5f that
this works for MSVC as well as GCC 4.5 Clang 3.0, so that should cover
all supported compilers.

This means we no longer need to explicitly handle new architectures
and as an added bonus also adds support for architectures where
unsigned long long cannot be used to hold pointers (e.g. CHERI).

Fixes: #101998


Full diff: https://github.com/llvm/llvm-project/pull/106155.diff

1 Files Affected:

  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h (+8-8)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h
index 3af47c2e2ff7a7..f8f03454ea169a 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h
@@ -138,19 +138,19 @@
 // in a portable way by the language itself.
 namespace __sanitizer {
 
-#if defined(_WIN64)
+#if defined(__UINTPTR_TYPE__)
+typedef __UINTPTR_TYPE__ uptr;
+typedef __INTPTR_TYPE__ sptr;
+#elif defined(_WIN64)
 // 64-bit Windows uses LLP64 data model.
 typedef unsigned long long uptr;
 typedef signed long long sptr;
-#else
-#  if (SANITIZER_WORDSIZE == 64) || SANITIZER_APPLE || SANITIZER_WINDOWS
-typedef unsigned long uptr;
-typedef signed long sptr;
-#  else
+#elif defined(_WIN32)
 typedef unsigned int uptr;
 typedef signed int sptr;
-#  endif
-#endif  // defined(_WIN64)
+#else
+#  error Unsupported compiler, missing __UINTPTR_TYPE__
+#endif  // defined(__UINTPTR_TYPE__)
 #if defined(__x86_64__)
 // Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
 // 64-bit pointer to unwind stack frame.

@mstorsjo
Copy link
Member

This change also breaks i686 mingw builds in the same way as #106135

In file included from /home/martin/code/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception_win.cpp:132:
In file included from /home/martin/clang-trunk/i686-w64-mingw32/include/windows.h:69:
In file included from /home/martin/clang-trunk/i686-w64-mingw32/include/windef.h:9:
In file included from /home/martin/clang-trunk/i686-w64-mingw32/include/minwindef.h:163:
In file included from /home/martin/clang-trunk/i686-w64-mingw32/include/winnt.h:150:
/home/martin/clang-trunk/i686-w64-mingw32/include/basetsd.h:147:39: error: typedef redefinition with different types ('ULONG_PTR' (aka 'unsigned long') vs '__sanitizer::uptr' (aka 'unsigned int'))
  147 |   __MINGW_EXTENSION typedef ULONG_PTR SIZE_T,*PSIZE_T;
      |                                       ^
/home/martin/code/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception.h:28:30: note: previous definition is here
   28 | typedef __sanitizer::uptr    SIZE_T;
      |                              ^
In file included from /home/martin/code/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception_win.cpp:132:
In file included from /home/martin/clang-trunk/i686-w64-mingw32/include/windows.h:69:
In file included from /home/martin/clang-trunk/i686-w64-mingw32/include/windef.h:9:
In file included from /home/martin/clang-trunk/i686-w64-mingw32/include/minwindef.h:163:
In file included from /home/martin/clang-trunk/i686-w64-mingw32/include/winnt.h:150:
/home/martin/clang-trunk/i686-w64-mingw32/include/basetsd.h:148:38: error: typedef redefinition with different types ('LONG_PTR' (aka 'long') vs '__sanitizer::sptr' (aka 'int'))
  148 |   __MINGW_EXTENSION typedef LONG_PTR SSIZE_T,*PSSIZE_T;
      |                                      ^
/home/martin/code/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception.h:29:30: note: previous definition is here
   29 | typedef __sanitizer::sptr    SSIZE_T;
      |                              ^
2 errors generated.

Copy link
Member

@mstorsjo mstorsjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Marking as request changes, to set the status for clarity.)

Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
@arichardson arichardson changed the base branch from main to users/arichardson/spr/main.compiler-rt-simplify-definition-of-uptr August 27, 2024 23:53
@arichardson
Copy link
Member Author

(Marking as request changes, to set the status for clarity.)

I've rebased this on top of #106311 which should hopefully fix the Windows issues you were seeing.

Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
Copy link

github-actions bot commented Aug 27, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

arichardson and others added 4 commits August 29, 2024 10:30
Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
@arichardson arichardson requested a review from mstorsjo September 4, 2024 16:46
@arichardson
Copy link
Member Author

@mstorsjo I confirmed that llvm-mingw ./build-compiler-rt.sh --build-sanitizers still works, okay to merge?

Copy link
Member

@mstorsjo mstorsjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks reasonable, and as you've tested that it works with llvm-mingw, I guess it works. I haven't tested building it with MSVC though.

@arichardson arichardson changed the base branch from users/arichardson/spr/main.compiler-rt-simplify-definition-of-uptr to main September 5, 2024 17:58
@arichardson arichardson merged commit 4d819da into main Sep 5, 2024
9 of 10 checks passed
@arichardson arichardson deleted the users/arichardson/spr/compiler-rt-simplify-definition-of-uptr branch September 5, 2024 17:58
@aeubanks
Copy link
Contributor

this has uncovered some nasty macro redefinitions in Linux headers which affects Android asan builds: https://crbug.com/365812505. can we revert this for now?

@arichardson
Copy link
Member Author

Oh that is rather nasty - it sounds like Clang has the wrong UINTPTR_TYPE for Android arm32? And I guess changing that could have surprising effects?

I am surprised you did not get a compiler error, the compiler-rt/lib/interception/interception_type_test.cpp file should have failed to compile (unless it happens that in that file asm/types.h is included first and redefines UINTPTR_TYPE.

I wonder if the workaround would be something like the following

#if defined(__arm) && defined(__linux__)
#include <asm/types.h>
#endif

Or alternatively just adding

#if defined(__arm) && defined(__linux__)
// Clang and the Linux Arm headers disagree on uintptr_t
typedef unsigned long uptr;
typedef unsigned long sptr;
#endif

@aeubanks
Copy link
Contributor

Oh that is rather nasty - it sounds like Clang has the wrong UINTPTR_TYPE for Android arm32? And I guess changing that could have surprising effects?
IIUC clang agrees with gcc, so clang isn't wrong, it's just that the kernel wants a different type as __UINTPTR_TYPE__ for some reason I don't understand.

I am surprised you did not get a compiler error, the compiler-rt/lib/interception/interception_type_test.cpp file should have failed to compile (unless it happens that in that file asm/types.h is included first and redefines UINTPTR_TYPE.
I'm not sure of the details, but yes either include order, or whether or not the Linux header is included at all changes behavior

I wonder if the workaround would be something like the following

#if defined(__arm) && defined(__linux__)
#include <asm/types.h>
#endif

Or alternatively just adding

#if defined(__arm) && defined(__linux__)
// Clang and the Linux Arm headers disagree on uintptr_t
typedef unsigned long uptr;
typedef unsigned long sptr;
#endif

I'll send out a PR that hardcodes uptr on Linux Arm

aeubanks added a commit to aeubanks/llvm-project that referenced this pull request Sep 10, 2024
After llvm#106155, Android arm32 asan builds stopped working with missing definition linker errors. This is due to inconsistent definitions of `uptr` of either `unsigned long` or `unsigned int` even between TUs in compiler-rt. This is caused by Linux arm32 headers redefining __UINTPTR_TYPE__ (see arch/arm/include/uapi/asm/types.h in the Linux kernel repo), meaning include order/whether or not the Linux header is included changes compiler-rt symbol mangling.

As a workaround, this hardcodes `uptr`/`sptr` in compiler-rt to `unsigned int`/`int` on Linux arm32, matching clang/gcc.
@nico
Copy link
Contributor

nico commented Sep 10, 2024

Is that still simpler than what we had before this PR then?

@arichardson
Copy link
Member Author

Even if it's slightly more verbose, the advantage of the new definition is that uptr now precisely matches the type of uintptr_t rather than just being the same size.

@nico
Copy link
Contributor

nico commented Sep 10, 2024

Except on Linux/arm, while previously things were fairly similar across platforms.

aeubanks added a commit that referenced this pull request Sep 11, 2024
After #106155, Android arm32 asan builds stopped working with missing
definition linker errors. This is due to inconsistent definitions of
`uptr` of either `unsigned long` or `unsigned int` even between TUs in
compiler-rt. This is caused by Linux arm32 headers redefining
`__UINTPTR_TYPE__` (see `arch/arm/include/uapi/asm/types.h` in the Linux
kernel repo), meaning include order/whether or not the Linux header is
included changes compiler-rt symbol mangling.

As a workaround, this hardcodes `uptr`/`sptr` in compiler-rt to
`unsigned int`/`int` on Linux arm32, matching clang/gcc.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants