@@ -575,11 +575,38 @@ Error, UINTPTR_MAX is undefined
575575#define UPB_LINKARR_APPEND (name ) \
576576 __attribute__ (( \
577577 section (" linkarr_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS
578- #define UPB_LINKARR_DECLARE (name, type ) \
579- extern type __start_linkarr_##name; \
580- extern type __stop_linkarr_##name; \
581- UPB_LINKARR_APPEND (name) \
582- UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1 ]
578+ #define UPB_LINKARR_DECLARE (name, type ) \
579+ extern type __start_linkarr_##name; \
580+ extern type __stop_linkarr_##name; \
581+ \
582+ /* This function defines a sentinel symbol that is used to ensure that the \
583+ * linker symbols __start_linkarr_##name and __stop_linkarr_##name are \
584+ * defined even if no (real) elements are added to the linkarr. \
585+ * \
586+ * We unfortunately have to use inline assembly here because GCC will \
587+ * refuse to create multiple sections with the same name and different \
588+ * flags: https://github.com/protocolbuffers/protobuf/issues/26385 \
589+ * \
590+ * We have to use a function wrapper in order to propagate `sizeof(type)` \
591+ * into the assembly (globally-scoped asm() blocks can't access values, \
592+ * even constant expressions). \
593+ */ \
594+ /* clang-format off */ \
595+ static __attribute__ ((used)) void upb_linkarr_wrapper_##name(void ) { \
596+ __asm__ volatile ( \
597+ " .pushsection linkarr_" #name " ,\" awR\" ,@progbits,unique,1\n\t " \
598+ " .p2align 8\n\t " \
599+ " .weak UPB_linkarr_internal_anchor_" #name " \n\t " \
600+ " .type UPB_linkarr_internal_anchor_" #name " , @object\n\t " \
601+ " UPB_linkarr_internal_anchor_" #name " :\n\t " \
602+ " .fill %c[size], 1, 0\n\t " \
603+ " .size UPB_linkarr_internal_anchor_" #name " , %c[size]\n\t " \
604+ " .popsection" \
605+ : \
606+ : [size] " n" (sizeof (type)) \
607+ ); \
608+ }
609+ /* clang-format on */
583610#define UPB_LINKARR_START (name ) (&__start_linkarr_##name)
584611#define UPB_LINKARR_STOP (name ) (&__stop_linkarr_##name)
585612
0 commit comments