Skip to content

Commit

Permalink
target: properly fix weak aliasing of probe NOPs on macOS
Browse files Browse the repository at this point in the history
@dragonmux got a report on Discord that the weak aliasing of probe
functions caused a linking error on macOS. I was able to reproduce
the issue by building BMP once with `-Dprobe=''`, then
reconfiguring with `-Dprobe='native'` and rebuilding.

Upon looking into the functions with Binary Ninja, I realised that the
true issue was that AppleClang does not support aliases *at all*.
Therefore, when saying "attribute weak" on the probe declaration, since
the alias never takes effect, the linker would then expect a framework
or library to supply the symbol [1].

The fix is to define a weak linkable pivot that will call the alias.
If a strong definition appears later, the linker will emit just that
definition. Otherwise, it'll emit an overridable pointer to the
weak definition in the symbol table.

This also lets us restore the visibility and inlining of the NOP probes.

This partially reverts commit 5e98f30.

[1]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/MachOTopics/1-Articles/executing_files.html#//apple_ref/doc/uid/TP40001829-98432-TPXREF120
  • Loading branch information
amyspark authored and dragonmux committed Jan 15, 2024
1 parent b9969de commit f9fb480
Showing 1 changed file with 31 additions and 16 deletions.
47 changes: 31 additions & 16 deletions src/target/target_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,34 @@
#include "target_probe.h"

#ifdef __APPLE__
// https://bugs.llvm.org/show_bug.cgi?id=17775
#define APPLE_STATIC
// https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html
#define DO_PRAGMA_(x) _Pragma(#x)
#define DO_PRAGMA(x) DO_PRAGMA_(x)
// __attribute__((alias)) is not supported in AppleClang.
#define weak_alias(name, aliasname) DO_PRAGMA(weak name = aliasname)
#define CORTEXAR_PROBE_WEAK_NOP(name) weak_alias(name, cortexar_probe_nop)
#define CORTEXM_PROBE_WEAK_NOP(name) weak_alias(name, cortexm_probe_nop)
#define TARGET_PROBE_WEAK_NOP(name) weak_alias(name, target_probe_nop)
#define LPC55_DP_PREPARE_WEAK_NOP(name) weak_alias(name, lpc55_dp_prepare_nop)
// __attribute__((alias)) is not supported in AppleClang, we need to define a
// __attribute__((weak)) placeholder body that'll get pivoted by the linker.
// if a "strong" definition is later available, the definition here will be
// removed at linking time.
// See:
// - https://bugs.llvm.org/show_bug.cgi?id=17775
// - "coalesced weak reference" in https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/MachOTopics/1-Articles/executing_files.html#//apple_ref/doc/uid/TP40001829-98432-TPXREF120
#define CORTEXAR_PROBE_WEAK_NOP(name) \
__attribute__((weak)) bool name(adiv5_access_port_s *const access_port, const target_addr_t base_address) \
{ \
return cortexar_probe_nop(access_port, base_address); \
}
#define CORTEXM_PROBE_WEAK_NOP(name) \
__attribute__((weak)) bool name(adiv5_access_port_s *const access_port) \
{ \
return cortexm_probe_nop(access_port); \
}
#define TARGET_PROBE_WEAK_NOP(name) \
__attribute__((weak)) bool name(target_s *const target) \
{ \
return target_probe_nop(target); \
}
#define LPC55_DP_PREPARE_WEAK_NOP(name) \
__attribute__((weak)) void name(adiv5_debug_port_s *const debug_port) \
{ \
lpc55_dp_prepare_nop(debug_port); \
};
#else
#define APPLE_STATIC static inline
#define CORTEXAR_PROBE_WEAK_NOP(name) \
extern bool name(adiv5_access_port_s *, target_addr_t) __attribute__((weak, alias("cortexar_probe_nop")));
#define CORTEXM_PROBE_WEAK_NOP(name) \
Expand All @@ -42,26 +57,26 @@
extern void name(adiv5_debug_port_s *) __attribute__((weak, alias("lpc55_dp_prepare_nop")));
#endif

APPLE_STATIC bool cortexar_probe_nop(adiv5_access_port_s *const access_port, const target_addr_t base_address)
static inline bool cortexar_probe_nop(adiv5_access_port_s *const access_port, const target_addr_t base_address)
{
(void)access_port;
(void)base_address;
return false;
}

APPLE_STATIC bool cortexm_probe_nop(adiv5_access_port_s *const access_port)
static inline bool cortexm_probe_nop(adiv5_access_port_s *const access_port)
{
(void)access_port;
return false;
}

APPLE_STATIC bool target_probe_nop(target_s *const target)
static inline bool target_probe_nop(target_s *const target)
{
(void)target;
return false;
}

APPLE_STATIC void lpc55_dp_prepare_nop(adiv5_debug_port_s *const debug_port)
static inline void lpc55_dp_prepare_nop(adiv5_debug_port_s *const debug_port)
{
(void)debug_port;
}
Expand Down

0 comments on commit f9fb480

Please sign in to comment.