// Macros to burn global values in custom sections so out-of-process
// profilers can locate them easily.
-
-#define GENERATE_DEBUG_SECTION(name, declaration) \
- _GENERATE_DEBUG_SECTION_WINDOWS(name) \
- _GENERATE_DEBUG_SECTION_APPLE(name) \
- declaration \
- _GENERATE_DEBUG_SECTION_LINUX(name)
+#define GENERATE_DEBUG_SECTION(name, declaration) \
+ _GENERATE_DEBUG_SECTION_WINDOWS(name) \
+ _GENERATE_DEBUG_SECTION_APPLE(name) \
+ declaration \
+ _GENERATE_DEBUG_SECTION_LINUX(name)
#if defined(MS_WINDOWS)
#define _GENERATE_DEBUG_SECTION_WINDOWS(name) \
- _Pragma(Py_STRINGIFY(section(Py_STRINGIFY(name), read, write))) \
- __declspec(allocate(Py_STRINGIFY(name)))
+ _Pragma(Py_STRINGIFY(section(Py_STRINGIFY(name), read, write))) \
+ __declspec(allocate(Py_STRINGIFY(name)))
#else
#define _GENERATE_DEBUG_SECTION_WINDOWS(name)
#endif
#if defined(__APPLE__)
#define _GENERATE_DEBUG_SECTION_APPLE(name) \
- __attribute__((section(SEG_DATA "," Py_STRINGIFY(name))))
+ __attribute__((section(SEG_DATA "," Py_STRINGIFY(name)))) \
+ __attribute__((used))
#else
#define _GENERATE_DEBUG_SECTION_APPLE(name)
#endif
#if defined(__linux__) && (defined(__GNUC__) || defined(__clang__))
#define _GENERATE_DEBUG_SECTION_LINUX(name) \
- __attribute__((section("." Py_STRINGIFY(name))))
+ __attribute__((section("." Py_STRINGIFY(name)))) \
+ __attribute__((used))
#else
#define _GENERATE_DEBUG_SECTION_LINUX(name)
#endif
static uintptr_t
get_async_debug(pid_t pid)
{
- return search_map_for_section(pid, "AsyncioDebug", "_asyncio.cpython");
+ uintptr_t result = search_map_for_section(pid, "AsyncioDebug", "_asyncio.cpython");
+ if (result == 0 && !PyErr_Occurred()) {
+ PyErr_SetString(PyExc_RuntimeError, "Cannot find AsyncioDebug section");
+ }
+ return result;
}
return 0;
}
+static int
+read_unsigned_long(pid_t pid, uintptr_t address, unsigned long *result)
+{
+ int bytes_read = read_memory(pid, address, sizeof(unsigned long), result);
+ if (bytes_read < 0) {
+ return -1;
+ }
+ return 0;
+}
+
static int
read_pyobj(pid_t pid, uintptr_t address, PyObject *ptr_addr)
{
return 0;
}
- char *digits = (char *)PyMem_RawMalloc(size * sizeof(digit));
+ digit *digits = (digit *)PyMem_RawMalloc(size * sizeof(digit));
if (!digits) {
PyErr_NoMemory();
return -1;
long value = 0;
+ // In theory this can overflow, but because of llvm/llvm-project#16778
+ // we can't use __builtin_mul_overflow because it fails to link with
+ // __muloti4 on aarch64. In practice this is fine because all we're
+ // testing here are task numbers that would fit in a single byte.
for (ssize_t i = 0; i < size; ++i) {
- long long factor;
- if (__builtin_mul_overflow(digits[i], (1UL << (ssize_t)(shift * i)),
- &factor)
- ) {
- goto error;
- }
- if (__builtin_add_overflow(value, factor, &value)) {
- goto error;
- }
+ long long factor = digits[i] * (1UL << (ssize_t)(shift * i));
+ value += factor;
}
PyMem_RawFree(digits);
if (negative) {
return NULL;
}
- int flags;
- err = read_int(
+ unsigned long flags;
+ err = read_unsigned_long(
pid,
(uintptr_t)task_name_obj.ob_type + offsets->type_object.tp_flags,
&flags);