diff --git a/.clang-format b/.clang-format index 6c1859a6..62f39b58 100644 --- a/.clang-format +++ b/.clang-format @@ -3,3 +3,5 @@ AlwaysBreakAfterDefinitionReturnType: All BreakBeforeBinaryOperators: None BinPackParameters: false SpaceAfterCStyleCast: true +SpaceBeforeParens: Always +AlignEscapedNewlines: DontAlign diff --git a/CMakeLists.txt b/CMakeLists.txt index 58ed3d89..28017a4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -735,6 +735,7 @@ message(" cxxflags release: ${CMAKE_CXX_FLAGS_RELEASE} " message(" 64-bit int: ${DBUS_INT64_TYPE} ") message(" 32-bit int: ${DBUS_INT32_TYPE} ") message(" 16-bit int: ${DBUS_INT16_TYPE} ") +message(" pointer size: ${DBUS_SIZEOF_VOID_P} ") message(" Doxygen: ${DOXYGEN} ") message(" Docbook Generator: ${DOCBOOK_GENERATOR_NAME} ") diff --git a/cmake/ConfigureChecks.cmake b/cmake/ConfigureChecks.cmake index bb2f021e..172db213 100644 --- a/cmake/ConfigureChecks.cmake +++ b/cmake/ConfigureChecks.cmake @@ -84,6 +84,8 @@ int main() { } " DBUS_USE_SYNC) +set(DBUS_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) + check_type_size("short" SIZEOF_SHORT) check_type_size("int" SIZEOF_INT) check_type_size("long" SIZEOF_LONG) diff --git a/configure.ac b/configure.ac index 033a1f8e..aee08dc7 100644 --- a/configure.ac +++ b/configure.ac @@ -429,13 +429,17 @@ winsock2.h ws2tcpip.h ]) +#### Pointer size +AC_CHECK_SIZEOF(void *) +DBUS_SIZEOF_VOID_P=$ac_cv_sizeof_void_p +AC_SUBST(DBUS_SIZEOF_VOID_P) + #### Integer sizes AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(int) -AC_CHECK_SIZEOF(void *) AC_CHECK_SIZEOF(long long) AC_CHECK_SIZEOF(__int64) @@ -1706,6 +1710,7 @@ echo " 64-bit int: ${DBUS_INT64_TYPE} 32-bit int: ${DBUS_INT32_TYPE} 16-bit int: ${DBUS_INT16_TYPE} + pointer size: ${DBUS_SIZEOF_VOID_P} Doxygen: ${DOXYGEN:-not found} xmlto: ${XMLTO:-not found} ducktype: ${DUCKTYPE:-not found} diff --git a/dbus/dbus-arch-deps.h.in b/dbus/dbus-arch-deps.h.in index 2dc58945..7b6328bc 100644 --- a/dbus/dbus-arch-deps.h.in +++ b/dbus/dbus-arch-deps.h.in @@ -46,6 +46,8 @@ typedef unsigned @DBUS_INT32_TYPE@ dbus_uint32_t; typedef @DBUS_INT16_TYPE@ dbus_int16_t; typedef unsigned @DBUS_INT16_TYPE@ dbus_uint16_t; +#define DBUS_SIZEOF_VOID_P @DBUS_SIZEOF_VOID_P@ + /* This is not really arch-dependent, but it's not worth * creating an additional generated header just for this */ diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h index c7967d24..4643053b 100644 --- a/dbus/dbus-internals.h +++ b/dbus/dbus-internals.h @@ -277,11 +277,27 @@ _dbus_assert_error_xor_bool (const DBusError *error, */ #define _DBUS_ALIGN_VALUE(this, boundary) \ - (( ((uintptr_t)(this)) + (((uintptr_t)(boundary)) -1)) & (~(((uintptr_t)(boundary))-1))) + ((((uintptr_t) (this)) + (((size_t) (boundary)) - 1)) & \ + (~(((size_t) (boundary)) - 1))) #define _DBUS_ALIGN_ADDRESS(this, boundary) \ ((void*)_DBUS_ALIGN_VALUE(this, boundary)) +#define _DBUS_IS_ALIGNED(this, boundary) \ + ((((size_t) (uintptr_t) (this)) & ((size_t) (boundary) - 1)) == 0) + +/** + * Aligning a pointer to _DBUS_ALIGNOF(dbus_max_align_t) guarantees that all + * scalar types can be loaded/stored from/to such an address without incurring + * an alignment fault (or a slow misaligned access). + * This is based on C11 max_align_t, but falls back to DBusBasicValue for + * older C standards. + */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +typedef max_align_t dbus_max_align_t; +#else +typedef DBusBasicValue dbus_max_align_t; +#endif DBUS_PRIVATE_EXPORT char* _dbus_strdup (const char *str); diff --git a/dbus/dbus-marshal-recursive.h b/dbus/dbus-marshal-recursive.h index c3b96819..5822e058 100644 --- a/dbus/dbus-marshal-recursive.h +++ b/dbus/dbus-marshal-recursive.h @@ -38,18 +38,19 @@ typedef struct DBusArrayLenFixup DBusArrayLenFixup; */ struct DBusTypeReader { + const DBusTypeReaderClass *klass; /**< the vtable for the reader */ + const DBusString *type_str; /**< string containing signature of block */ + const DBusString *value_str; /**< string containing values of block */ + dbus_uint32_t byte_order : 8; /**< byte order of the block */ dbus_uint32_t finished : 1; /**< marks we're at end iterator for cases * where we don't have another way to tell */ dbus_uint32_t array_len_offset : 3; /**< bytes back from start_pos that len ends */ - const DBusString *type_str; /**< string containing signature of block */ int type_pos; /**< current position in signature */ - const DBusString *value_str; /**< string containing values of block */ int value_pos; /**< current position in values */ - const DBusTypeReaderClass *klass; /**< the vtable for the reader */ union { struct { @@ -63,6 +64,8 @@ struct DBusTypeReader */ struct DBusTypeWriter { + DBusString *type_str; /**< where to write typecodes (or read type expectations) */ + DBusString *value_str; /**< where to write values */ dbus_uint32_t byte_order : 8; /**< byte order to write values with */ dbus_uint32_t container_type : 8; /**< what are we inside? (e.g. struct, variant, array) */ @@ -71,9 +74,7 @@ struct DBusTypeWriter dbus_uint32_t enabled : 1; /**< whether to write values */ - DBusString *type_str; /**< where to write typecodes (or read type expectations) */ int type_pos; /**< current pos in type_str */ - DBusString *value_str; /**< where to write values */ int value_pos; /**< next position to write */ union diff --git a/dbus/dbus-mempool.c b/dbus/dbus-mempool.c index 38c019a7..dc0b4467 100644 --- a/dbus/dbus-mempool.c +++ b/dbus/dbus-mempool.c @@ -82,19 +82,31 @@ struct DBusMemBlock * when we free the mem pool. */ - /* this is a long so that "elements" is aligned */ - long used_so_far; /**< bytes of this block already allocated as elements. */ - - unsigned char elements[]; /**< the block data, actually allocated to required size */ + size_t used_so_far; /**< bytes of this block already allocated as elements. */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) + /* + * Ensure that elements is aligned correctly. For all supported pre-C11 + * targets, the size_t above should ensure that the elements array is + * sufficiently aligned (this is checked in the static assert below). + */ + _Alignas (dbus_max_align_t) +#endif + unsigned char elements[]; /**< the block data, actually allocated to required size */ }; +_DBUS_STATIC_ASSERT (_DBUS_IS_ALIGNED (sizeof (struct DBusMemBlock), + _DBUS_ALIGNOF (dbus_max_align_t))); +_DBUS_STATIC_ASSERT (_DBUS_IS_ALIGNED (offsetof (struct DBusMemBlock, + elements), + _DBUS_ALIGNOF (dbus_max_align_t))); + /** * Internals fields of DBusMemPool */ struct DBusMemPool { - int element_size; /**< size of a single object in the pool */ - int block_size; /**< size of most recently allocated block */ + size_t element_size; /**< size of a single object in the pool */ + size_t block_size; /**< size of most recently allocated block */ unsigned int zero_elements : 1; /**< whether to zero-init allocated elements */ DBusFreedElement *free_elements; /**< a free list of elements to recycle */ @@ -152,10 +164,11 @@ _dbus_mem_pool_new (int element_size, _dbus_assert (element_size >= (int) sizeof (void*)); _dbus_assert (element_size >= (int) sizeof (DBusFreedElement)); - /* align the element size to a pointer boundary so we won't get bus - * errors under other architectures. + /* align the element size to be suitable for the most-aligned type + * that we care about (in practice usually a pointer). */ - pool->element_size = _DBUS_ALIGN_VALUE (element_size, sizeof (void *)); + pool->element_size = + _DBUS_ALIGN_VALUE (element_size, _DBUS_ALIGNOF (dbus_max_align_t)); pool->zero_elements = zero_elements != FALSE; @@ -215,7 +228,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) if (_dbus_disable_mem_pools ()) { DBusMemBlock *block; - int alloc_size; + size_t alloc_size; /* This is obviously really silly, but it's * debug-mode-only code that is compiled out @@ -223,9 +236,9 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) * is a constant expression FALSE so this block * should vanish) */ - + alloc_size = sizeof (DBusMemBlock) + pool->element_size; - + if (pool->zero_elements) block = dbus_malloc0 (alloc_size); else @@ -239,6 +252,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) VALGRIND_MEMPOOL_ALLOC (pool, (void *) &block->elements[0], pool->element_size); + _dbus_assert (_DBUS_IS_ALIGNED (&block->elements[0], + _DBUS_ALIGNOF (dbus_max_align_t))); return (void*) &block->elements[0]; } else @@ -264,7 +279,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) memset (element, '\0', pool->element_size); pool->allocated_elements += 1; - + _dbus_assert ( + _DBUS_IS_ALIGNED (element, _DBUS_ALIGNOF (dbus_max_align_t))); return element; } else @@ -276,7 +292,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) { /* Need a new block */ DBusMemBlock *block; - int alloc_size; + size_t alloc_size; #ifdef DBUS_ENABLE_EMBEDDED_TESTS int saved_counter; #endif @@ -306,6 +322,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) block = dbus_malloc0 (alloc_size); else block = dbus_malloc (alloc_size); + _dbus_assert ( + _DBUS_IS_ALIGNED (block, _DBUS_ALIGNOF (dbus_max_align_t))); #ifdef DBUS_ENABLE_EMBEDDED_TESTS _dbus_set_fail_alloc_counter (saved_counter); @@ -319,14 +337,16 @@ _dbus_mem_pool_alloc (DBusMemPool *pool) block->next = pool->blocks; pool->blocks = block; } - + element = &pool->blocks->elements[pool->blocks->used_so_far]; - + pool->blocks->used_so_far += pool->element_size; pool->allocated_elements += 1; VALGRIND_MEMPOOL_ALLOC (pool, element, pool->element_size); + _dbus_assert ( + _DBUS_IS_ALIGNED (element, _DBUS_ALIGNOF (dbus_max_align_t))); return element; } } diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index a87043e3..6f2a518d 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -136,6 +136,15 @@ struct DBusMessageRealIter } u; /**< the type writer or reader that does all the work */ }; +#if DBUS_SIZEOF_VOID_P > 8 +/* + * Architectures with 128-bit pointers were not supported in DBus 1.10, so we + * do no check for DBus 1.10 structure layout compatibility for such + * architectures (e.g. Arm Morello). + */ +#define CHECK_DBUS_1_10_BINARY_COMPATIBILITY 0 +#else +#define CHECK_DBUS_1_10_BINARY_COMPATIBILITY 1 /** * Layout of a DBusMessageIter on the stack in dbus 1.10.0. This is no * longer used, but for ABI compatibility we need to assert that the @@ -158,6 +167,7 @@ typedef struct int pad2; void *pad3; } DBusMessageIter_1_10_0; +#endif static void get_const_signature (DBusHeader *header, @@ -2069,17 +2079,23 @@ _dbus_message_iter_init_common (DBusMessage *message, _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <= _DBUS_ALIGNOF (DBusMessageIter)); +#if CHECK_DBUS_1_10_BINARY_COMPATIBILITY /* A failure of these two assertions would indicate that we've broken * ABI on this platform since 1.10.0. */ _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) == sizeof (DBusMessageIter)); _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) == _DBUS_ALIGNOF (DBusMessageIter)); +#endif /* If this static assertion fails, it means the DBusMessageIter struct * is not "packed", which might result in "iter = other_iter" not copying * every byte. */ +#if DBUS_SIZEOF_VOID_P > 8 + _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) == 16 * sizeof (void *)); +#else _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) == 4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int)); +#endif /* Since the iterator will read or write who-knows-what from the * message, we need to get in the right byte order diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index da2f2d9d..931917f5 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -59,7 +59,10 @@ typedef struct DBusMessageIter DBusMessageIter; * DBusMessageIter struct; contains no public fields. */ struct DBusMessageIter -{ +{ +#if DBUS_SIZEOF_VOID_P > 8 + void *dummy[16]; /**< Don't use this */ +#else void *dummy1; /**< Don't use this */ void *dummy2; /**< Don't use this */ dbus_uint32_t dummy3; /**< Don't use this */ @@ -74,12 +77,24 @@ struct DBusMessageIter int pad1; /**< Don't use this */ void *pad2; /**< Don't use this */ void *pad3; /**< Don't use this */ +#endif }; /** * A message iterator for which dbus_message_iter_abandon_container_if_open() * is the only valid operation. */ +#if DBUS_SIZEOF_VOID_P > 8 +#define DBUS_MESSAGE_ITER_INIT_CLOSED \ +{ \ + { \ + NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL \ + } \ +} +#else #define DBUS_MESSAGE_ITER_INIT_CLOSED \ { \ NULL, /* dummy1 */ \ @@ -97,6 +112,7 @@ struct DBusMessageIter NULL, /* pad2 */ \ NULL /* pad3 */ \ } +#endif DBUS_EXPORT DBusMessage* dbus_message_new (int message_type); diff --git a/meson.build b/meson.build index 9103bb0e..31c6df51 100644 --- a/meson.build +++ b/meson.build @@ -276,6 +276,8 @@ foreach type : int_types endif endforeach +arch_config.set('DBUS_SIZEOF_VOID_P', cc.sizeof('void *')) + ############################################################################### # Dependencies @@ -1195,6 +1197,7 @@ summary_dict += { '64-bit int': arch_config.get('DBUS_INT64_TYPE'), '32-bit int': arch_config.get('DBUS_INT32_TYPE'), '16-bit int': arch_config.get('DBUS_INT16_TYPE'), + 'pointer size': arch_config.get('DBUS_SIZEOF_VOID_P'), 'xsltproc': xsltproc.found() ? xsltproc.full_path() : '', 'Doxygen': doxygen.found() ? doxygen.full_path() : '', 'ducktype': ducktype.found() ? ducktype.full_path() : '',