From 7f99a41011507ee17900522b7577f89e82db070f Mon Sep 17 00:00:00 2001
From: Aditya Kamath <Aditya.Kamath1@ibm.com>
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<ppc_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

