|
| 1 | +From 37d454721a6e3c2c54303bbcb35f0124de9bb51e Mon Sep 17 00:00:00 2001 |
| 2 | +From: Mark Wielaard <mark@klomp.org> |
| 3 | +Date: Mon, 18 Aug 2025 15:30:47 +0200 |
| 4 | +Subject: [PATCH] Add ppc64le linux hardwire for ld64.so.2 strcmp |
| 5 | + |
| 6 | +When dlopen is used we might end up in an assembly powerpc/strcmp.S |
| 7 | +variant that is optimized in a way memcheck cannot proof correct. We |
| 8 | +try to intercept strcmp in ld.so, but might fail when strcmp is called |
| 9 | +before our interception code is loaded. Having an hardwire for ld.so |
| 10 | +strcmp (earlier intercept) would solve this. |
| 11 | + |
| 12 | +https://bugs.kde.org/show_bug.cgi?id=508145 |
| 13 | + |
| 14 | +(cherry picked from commit 78fe3625f6b8ed4de28527d71c4a98d70e5b3035) |
| 15 | +--- |
| 16 | + NEWS | 1 + |
| 17 | + coregrind/m_redir.c | 6 +++++ |
| 18 | + coregrind/m_trampoline.S | 45 +++++++++++++++++++++++++++++++++ |
| 19 | + coregrind/pub_core_trampoline.h | 1 + |
| 20 | + 4 files changed, 53 insertions(+) |
| 21 | + |
| 22 | +diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c |
| 23 | +index 63172b971..857f910cb 100644 |
| 24 | +--- a/coregrind/m_redir.c |
| 25 | ++++ b/coregrind/m_redir.c |
| 26 | +@@ -1504,14 +1504,20 @@ void VG_(redir_initialise) ( void ) |
| 27 | + |
| 28 | + add_hardwired_spec( |
| 29 | + "ld64.so.2", "index", |
| 30 | + (Addr)&VG_(ppc64_linux_REDIR_FOR_strchr), |
| 31 | + NULL /* not mandatory - so why bother at all? */ |
| 32 | + /* glibc-2.5 (FC6, ppc64) seems fine without it */ |
| 33 | + ); |
| 34 | ++ |
| 35 | ++ add_hardwired_spec( |
| 36 | ++ "ld64.so.2", "strcmp", |
| 37 | ++ (Addr)&VG_(ppc64_linux_REDIR_FOR_strcmp), |
| 38 | ++ NULL |
| 39 | ++ ); |
| 40 | + } |
| 41 | + |
| 42 | + # elif defined(VGP_arm_linux) |
| 43 | + /* If we're using memcheck, use these intercepts right from the |
| 44 | + start, otherwise ld.so makes a lot of noise. In most ARM-linux |
| 45 | + distros, ld.so's soname is ld-linux.so.3, but Ubuntu 14.04 on |
| 46 | + Odroid uses ld-linux-armhf.so.3 for some reason. */ |
| 47 | +diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S |
| 48 | +index 2c2cc0dc2..af25c8f7a 100644 |
| 49 | +--- a/coregrind/m_trampoline.S |
| 50 | ++++ b/coregrind/m_trampoline.S |
| 51 | +@@ -600,14 +600,59 @@ VG_(ppc64_linux_REDIR_FOR_strchr): |
| 52 | + li 3,0 |
| 53 | + blr |
| 54 | + .long 0 |
| 55 | + .byte 0,0,0,0,0,0,0,0 |
| 56 | + .L1end: |
| 57 | + |
| 58 | + |
| 59 | ++ /* this function is written using the "dotless" ABI convention */ |
| 60 | ++ .align 2 |
| 61 | ++ .globl VG_(ppc64_linux_REDIR_FOR_strcmp) |
| 62 | ++#if !defined VGP_ppc64be_linux || _CALL_ELF == 2 |
| 63 | ++ /* Little Endian uses ELF version 2 */ |
| 64 | ++ .type VG_(ppc64_linux_REDIR_FOR_strcmp),@function |
| 65 | ++VG_(ppc64_linux_REDIR_FOR_strcmp): |
| 66 | ++#else |
| 67 | ++ /* Big Endian uses ELF version 1 */ |
| 68 | ++ .section ".opd","aw" |
| 69 | ++ .align 3 |
| 70 | ++VG_(ppc64_linux_REDIR_FOR_strcmp): |
| 71 | ++ .quad .L.VG_(ppc64_linux_REDIR_FOR_strcmp),.TOC.@tocbase,0 |
| 72 | ++ .previous |
| 73 | ++ .size VG_(ppc64_linux_REDIR_FOR_strcmp), \ |
| 74 | ++ .LFE0-.L.VG_(ppc64_linux_REDIR_FOR_strcmp) |
| 75 | ++ .type VG_(ppc64_linux_REDIR_FOR_strcmp), @function |
| 76 | ++ |
| 77 | ++.L.VG_(ppc64_linux_REDIR_FOR_strcmp): |
| 78 | ++#endif |
| 79 | ++#if _CALL_ELF == 2 |
| 80 | ++0: addis 2,12,.TOC.-0b@ha |
| 81 | ++ addi 2,2,.TOC.-0b@l |
| 82 | ++ .localentry VG_(ppc64_linux_REDIR_FOR_strcmp), .-VG_(ppc64_linux_REDIR_FOR_strcmp) |
| 83 | ++#endif |
| 84 | ++.LFB0: |
| 85 | ++ .cfi_startproc |
| 86 | ++ li 10,0 |
| 87 | ++.L3: |
| 88 | ++ lbzx 8,3,10 |
| 89 | ++ lbzx 9,4,10 |
| 90 | ++ cmpwi 0,8,0 |
| 91 | ++ beq 0,.L2 |
| 92 | ++ cmpw 0,8,9 |
| 93 | ++ addi 10,10,1 |
| 94 | ++ beq 0,.L3 |
| 95 | ++.L2: |
| 96 | ++ subf 3,9,8 |
| 97 | ++ extsw 3,3 |
| 98 | ++ blr |
| 99 | ++ .long 0 |
| 100 | ++ .byte 0,0,0,0,0,0,0,0 |
| 101 | ++ .cfi_endproc |
| 102 | ++.LFE0: |
| 103 | ++ |
| 104 | + .global VG_(trampoline_stuff_end) |
| 105 | + VG_(trampoline_stuff_end): |
| 106 | + |
| 107 | + /* and a trailing page of unexecutable code */ |
| 108 | + UD2_PAGE |
| 109 | + |
| 110 | + # undef UD2_16 |
| 111 | +diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h |
| 112 | +index 11d791df7..92b4fc67b 100644 |
| 113 | +--- a/coregrind/pub_core_trampoline.h |
| 114 | ++++ b/coregrind/pub_core_trampoline.h |
| 115 | +@@ -93,14 +93,15 @@ extern UInt VG_(ppc32_linux_REDIR_FOR_strlen)( void* ); |
| 116 | + extern UInt VG_(ppc32_linux_REDIR_FOR_strcmp)( void*, void* ); |
| 117 | + extern void* VG_(ppc32_linux_REDIR_FOR_strchr)( void*, Int ); |
| 118 | + #endif |
| 119 | + |
| 120 | + #if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) |
| 121 | + extern Addr VG_(ppc64_linux_SUBST_FOR_rt_sigreturn); |
| 122 | + extern UInt VG_(ppc64_linux_REDIR_FOR_strlen)( void* ); |
| 123 | ++extern UInt VG_(ppc64_linux_REDIR_FOR_strcmp)( void*, void* ); |
| 124 | + extern void* VG_(ppc64_linux_REDIR_FOR_strchr)( void*, Int ); |
| 125 | + /* A label (sans dot) marking the ultra-magical return stub via which |
| 126 | + all redirected and wrapped functions are made to "return" on |
| 127 | + ppc64-linux. The one insn at this label is never really |
| 128 | + translated. Instead, m_translate generates IR to restore the |
| 129 | + thread's LR and R2 registers from a small stack in the ppc64 guest |
| 130 | + state structure, and then branch to LR. Convoluted? Confusing? |
| 131 | +-- |
| 132 | +2.51.0 |
| 133 | + |
0 commit comments