|
204 | 204 | *(unsigned long long*)(fn + 12) = (unsigned long long)fn_stub;\ |
205 | 205 | CACHEFLUSH((char *)fn, CODESIZE); |
206 | 206 | #define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub) |
| 207 | +#elif defined(__powerpc64__) && __LITTLE_ENDIAN__ |
| 208 | + // For ppc64le (ELFv2 ABI with function descriptors) |
| 209 | + #define CODESIZE 36U |
| 210 | + #define CODESIZE_MIN 36U |
| 211 | + #define CODESIZE_MAX CODESIZE |
| 212 | + /* |
| 213 | + * This hook loads the address of the stub function's descriptor, |
| 214 | + * then loads the code entry point and TOC address from the descriptor, |
| 215 | + * and finally performs an indirect branch. |
| 216 | + * |
| 217 | + * Assembly equivalence: |
| 218 | + * // Step 1: Load the 64-bit address of the function descriptor for `fn_stub` into r11 |
| 219 | + * lis r11, fn_stub_desc@highest |
| 220 | + * ori r11, r11, fn_stub_desc@higher |
| 221 | + * rldicr r11, r11, 32, 31 |
| 222 | + * ori r11, r11, fn_stub_desc@h |
| 223 | + * ori r11, r11, fn_stub_desc@l |
| 224 | + * |
| 225 | + * // Step 2: Load values from the function descriptor |
| 226 | + * ld r12, 0(r11) // Load code address into r12 from descriptor |
| 227 | + * ld r2, 8(r11) // Load TOC address into r2 from descriptor |
| 228 | + * |
| 229 | + * // Step 3: Branch |
| 230 | + * mtctr r12 // Move code address to Count Register |
| 231 | + * bctr // Branch to the address in CTR |
| 232 | + */ |
| 233 | + #define REPLACE_FAR(t, fn, fn_stub)\ |
| 234 | + do {\ |
| 235 | + uint64_t desc_addr = (uint64_t)fn_stub;\ |
| 236 | + uint32_t* p = (uint32_t*)fn;\ |
| 237 | + /* Load 64-bit descriptor address into r11 */ \ |
| 238 | + p[0] = 0x3d600000 | (uint32_t)(desc_addr >> 48);\ |
| 239 | + p[1] = 0x616b0000 | (uint32_t)((desc_addr >> 32) & 0xFFFF);\ |
| 240 | + p[2] = 0x796b07c6 | (uint32_t)(32 << 21) | (31 << 16);\ |
| 241 | + p[3] = 0x616b0000 | (uint32_t)((desc_addr >> 16) & 0xFFFF);\ |
| 242 | + p[4] = 0x616b0000 | (uint32_t)(desc_addr & 0xFFFF);\ |
| 243 | + /* ld r12, 0(r11) */ \ |
| 244 | + p[5] = 0xe98b0000;\ |
| 245 | + /* ld r2, 8(r11) */ \ |
| 246 | + p[6] = 0xe84b0008;\ |
| 247 | + /* mtctr r12 */ \ |
| 248 | + p[7] = 0x7d8903a6;\ |
| 249 | + /* bctr */ \ |
| 250 | + p[8] = 0x4e800420;\ |
| 251 | + CACHEFLUSH((char *)fn, CODESIZE);\ |
| 252 | + } while(0) |
| 253 | + #define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub) |
| 254 | + |
207 | 255 | #elif defined(__powerpc64__) |
208 | 256 | #define CODESIZE 28U |
209 | 257 | #define CODESIZE_MIN 28U |
|
0 commit comments