From 7f99a41011507ee17900522b7577f89e82db070f Mon Sep 17 00:00:00 2001 From: Aditya Kamath Date: Wed, 17 Jun 2026 06:25:26 -0500 Subject: [PATCH 2/3] Add 32 bitr non pthread binary support for VAPI --- gdb/rs6000-aix-tdep.c | 101 ++++++++++++++++++++++++------------------ gdb/rs6000-aix-vapi.h | 15 +++++++ gdb/rs6000-tdep.c | 22 ++++++++- 3 files changed, 93 insertions(+), 45 deletions(-) diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c index 8c375a31e50..d6614077b1d 100644 --- a/gdb/rs6000-aix-tdep.c +++ b/gdb/rs6000-aix-tdep.c @@ -451,76 +451,89 @@ rs6000_aix_adjust_vapi_lr (const frame_info_ptr &frame, CORE_ADDR pc, CORE_ADDR *lr, int wordsize, enum bfd_endian byte_order) { - /* Check if PC or LR is in VAPI glue code range */ - CORE_ADDR pc_low = pc & 0xFFFF; + /* Check if LR is in VAPI glue code range */ CORE_ADDR lr_low = *lr & 0xFFFF; - bool pc_in_vapi = false; bool lr_in_vapi = false; if (wordsize == 8) /* 64-bit */ { - pc_in_vapi = (pc_low >= vapi_addr_64 && pc_low < vapi_glue_addr_high); lr_in_vapi = (lr_low >= vapi_addr_64 && lr_low < vapi_glue_addr_high); } else /* 32-bit */ { - pc_in_vapi = (pc_low >= vapi_glue_addr_low); lr_in_vapi = (lr_low >= vapi_glue_addr_low); } - /* Only adjust if PC or LR is in VAPI glue range */ - if (!pc_in_vapi && !lr_in_vapi) + /* Only adjust if LR is in VAPI glue range */ + if (!lr_in_vapi) return false; - if (pc_in_vapi) - { - gdb_printf (gdb_stdlog, - "rs6000_in_vapi_glue_code: PC 0x%s (low=0x%x) detected as VAPI glue (%d-bit)\n", - phex_nz (pc, wordsize), - (unsigned int)pc_low, - wordsize * 8); - } + //gdb_printf (gdb_stdlog, + // "rs6000_aix_adjust_vapi_lr: LR 0x%s (low=0x%x) detected as VAPI glue (%d-bit)\n", + // phex_nz (*lr, wordsize), + // (unsigned int)lr_low, + // wordsize * 8); /* Try to get real LR from VAPI control block in TLS */ try { struct gdbarch *gdbarch = get_frame_arch (frame); ppc_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + CORE_ADDR vapi_lr_addr = 0; + CORE_ADDR tls_base = 0; - CORE_ADDR tls_base = get_frame_register_unsigned (frame, - tdep->ppc_gp0_regnum + 13); + /* For 64-bit, use r13 register (works reliably) */ + if (wordsize == 8) + { + tls_base = get_frame_register_unsigned (frame, + tdep->ppc_gp0_regnum + 13); + + if (tls_base != 0) + vapi_lr_addr = tls_base - VAPI_CB_OFFSET_64 + VAPI_SAVED_LR_OFFSET; + } + /* For 32-bit, SPRG3 (not r13) holds the thread pointer and is at a fixed + address. r13 returns 0xdeadbeef because ptrace cannot read SPRG3. */ + else + { + /* In 32-bit AIX, SPRG3 always points to a fixed address. + This is the thread pointer for 32-bit programs. */ + tls_base = VAPI_CB_ADDR_32_NOTHREADS; + vapi_lr_addr = tls_base + VAPI_SAVED_LR_OFFSET; + + gdb_printf (gdb_stdlog, + "rs6000_aix_adjust_vapi_lr: Using fixed SPRG3=0x%s, " + "v_save_lr at 0x%s for 32-bit\n", + phex_nz (tls_base, wordsize), + phex_nz (vapi_lr_addr, wordsize)); + } - if (tls_base != 0) - { - CORE_ADDR vapi_lr_addr; - - /* Calculate VAPI LR address using standard offset */ - if (wordsize == 8) - vapi_lr_addr = tls_base - VAPI_CB_OFFSET_64 + 8; - else - vapi_lr_addr = tls_base - VAPI_CB_OFFSET_32 + 8; - - gdb_byte vapi_buf[8]; - if (target_read_memory (vapi_lr_addr, vapi_buf, wordsize) == 0) - { - CORE_ADDR vapi_lr_value = extract_unsigned_integer (vapi_buf, - wordsize, - byte_order); - - if (vapi_lr_value != 0 && vapi_lr_value != *lr) - { - //gdb_printf (gdb_stdlog, - // "rs6000_frame_cache: Using VAPI v_save_lr 0x%s from TLS\n", - // phex_nz (vapi_lr_value, wordsize)); - *lr = vapi_lr_value; - return true; - } - } - } + /* Read the saved LR from VAPI control block */ + if (vapi_lr_addr != 0) + { + gdb_byte vapi_buf[8]; + if (target_read_memory (vapi_lr_addr, vapi_buf, wordsize) == 0) + { + CORE_ADDR vapi_lr_value = extract_unsigned_integer (vapi_buf, + wordsize, + byte_order); + + if (vapi_lr_value != 0 && vapi_lr_value != *lr) + { + //gdb_printf (gdb_stdlog, + // "rs6000_aix_adjust_vapi_lr: Using VAPI v_save_lr 0x%s from TLS\n", + // phex_nz (vapi_lr_value, wordsize)); + *lr = vapi_lr_value; + return true; + } + } + } } catch (const gdb_exception_error &ex) { /* Ignore errors, don't adjust LR */ + //gdb_printf (gdb_stdlog, + //"rs6000_aix_adjust_vapi_lr: Exception caught: %s\n", + //ex.what ()); } return false; diff --git a/gdb/rs6000-aix-vapi.h b/gdb/rs6000-aix-vapi.h index f7e2477df20..761ecda9312 100644 --- a/gdb/rs6000-aix-vapi.h +++ b/gdb/rs6000-aix-vapi.h @@ -70,6 +70,21 @@ #define VAPI_CB_OFFSET_64 \ (TLS_POINTER_OFFSET64 + VAPI_CB_SIZE_64 + TLSCB_BASE_SIZE64) +/* ======================================================================== + Fixed VAPI Control Block Address and Offsets for 32-bit Programs + ======================================================================== */ + +/* For 32-bit programs, SPRG3 (not r13) holds the thread pointer and always + points to this fixed address. */ +#define VAPI_CB_ADDR_32_NOTHREADS 0x2ff22ef0 + +/* The saved LR (v_save_lr) is at offset +8 from VAPI CB base for both + 32-bit and 64-bit. The VAPI control block structure: + +0: version/magic (0x00110000) + +4: "VAPI" signature (0x56415049) + +8: v_save_lr (saved link register) */ +#define VAPI_SAVED_LR_OFFSET 8 + /* ======================================================================== VAPI Glue Code Address Ranges ======================================================================== */ diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 9e638fd2742..6a3c05e2cd8 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -55,6 +55,7 @@ #include "solib-svr4.h" #include "ppc-tdep.h" #include "ppc-ravenscar-thread.h" +#include "rs6000-aix-vapi.h" #include "dis-asm.h" @@ -3589,7 +3590,26 @@ rs6000_frame_cache (const frame_info_ptr &this_frame, void **this_cache) func = get_frame_func (this_frame); cache->pc = func; pc = get_frame_pc (this_frame); - skip_prologue (gdbarch, func, pc, &fdata); + + /* Check if PC is in VAPI glue code. If so, we need special handling + because VAPI glue is frameless and doesn't save LR normally. */ + CORE_ADDR pc_low = pc & 0xFFFF; + bool pc_in_vapi = ((wordsize == 8 && pc_low >= vapi_addr_64 && pc_low < vapi_glue_addr_high) || + (wordsize == 4 && pc_low >= vapi_glue_addr_low)); + + if (pc_in_vapi && tdep->ppc_adjust_trampoline_lr != nullptr) + { + /* PC is in VAPI glue - mark as frameless and set LR to read from VAPI CB */ + fdata.frameless = 1; + fdata.lr_offset = 0; + + //gdb_printf (gdb_stdlog, + // "rs6000_frame_cache: PC in VAPI glue, using VAPI control block for LR\n"); + } + else + { + skip_prologue (gdbarch, func, pc, &fdata); + } /* Figure out the parent's stack pointer. */ -- 2.51.2