[v1] PowerPC: Use -mcmodel=large for the compile command

Message ID 20260728064909.1080844-1-abhay@linux.ibm.com
State New
Headers
Series [v1] PowerPC: Use -mcmodel=large for the compile command |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 fail Patch failed to apply
linaro-tcwg-bot/tcwg_gdb_check--master-arm fail Patch failed to apply

Commit Message

Abhay Kandpal July 28, 2026, 6:49 a.m. UTC
  On ppc64le, the "compile" command produces corrupted code when the
compiled expression takes the address of a symbol in the inferior.
For example:

  (gdb) break -qualified main
  (gdb) run
  (gdb) compile code pmf = &A::get_var1
  (gdb) x/2gx &pmf
  0x7fffffffeb68:  0x0000800010000d78  0x0000000000000000

The stored address is wrong: the low 32 bits are correct
(0x10000d78, the true address of A::get_var1) but bit 47 is
incorrectly set.  When the compiled code later calls through such a
pointer the inferior jumps to unmapped memory and receives SIGSEGV.

The cause is the code model used to compile the injected object.
Commit 533f04079c7 ("[gdb] [rs6000] Add
ppc64_linux_gcc_target_options method.") made ppc64 return an empty
string from gdbarch_gcc_target_options, overriding the
"-mcmodel=large" that default_gcc_target_options supplies for 64-bit
targets, so GCC falls back to -mcmodel=medium.

With the medium model, references to the inferior's symbols are
compiled as TOC-relative accesses using R_PPC64_TOC16_HA/LO
relocations, whose combined displacement is a signed 32-bit value
(+/- 2GB).  GDB allocates the compiled module in the inferior with an
mmap that the kernel places in the high mmap region (e.g. around
0x7ffff7f30000), while the inferior's own text is low (e.g. around
0x10000000).  The distance between them is close to 2^47, far beyond
the reach of a TOC16 relocation, so the displacement is silently
truncated to 32 bits, producing an address that is off by 2^47.

Restore -mcmodel=large for ppc64.  With the large model GCC emits a
real .toc section and loads symbol addresses as full 64-bit values
from it, so the only TOC-relative references are into the module's
own .toc, which is always in range regardless of where the module is
mapped.  The .TOC. handling added by commit bad23de3543 ("[gdb]
Handle .TOC. sections during gdb-compile for rs6000 target.")
continues to work; it now resolves via the module's genuine .toc
section rather than the .text fallback that the medium model
required.

Tested on powerpc64le-linux (Fedora, GCC 15.2.1).

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34456

gdb/
	* ppc-linux-tdep.c (ppc64_linux_gcc_target_options): Return
	"-mcmodel=large".
---
This patch is reg tested.

 gdb/ppc-linux-tdep.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
  

Comments

Ulrich Weigand July 28, 2026, 10:24 a.m. UTC | #1
Abhay Kandpal <abhay@linux.ibm.com> wrote:

>The cause is the code model used to compile the injected object.
>Commit 533f04079c7 ("[gdb] [rs6000] Add
>ppc64_linux_gcc_target_options method.") made ppc64 return an empty
>string from gdbarch_gcc_target_options, overriding the
>"-mcmodel=large" that default_gcc_target_options supplies for 64-bit
>targets, so GCC falls back to -mcmodel=medium.

I can see why large model is more appropriate for this type
of compilation.  However, your patch just reverts the effect
of the above commit, without actually reverting it.  (This
causes ppc64_linux_gcc_target_options to pretty much duplicate
default_gcc_target_options.)  I think it would be preferable
to fully revert the commit instead.

Bye,
Ulrich
  
Abhay Kandpal July 28, 2026, 5:49 p.m. UTC | #2
Thanks Ulrich — v2 fully reverts 533f04079c7 as you suggested, so ppc64 
uses default_gcc_target_options. BR, Abhay

On 28/07/26 15:54, Ulrich Weigand wrote:
> Abhay Kandpal<abhay@linux.ibm.com> wrote:
>
>> The cause is the code model used to compile the injected object.
>> Commit 533f04079c7 ("[gdb] [rs6000] Add
>> ppc64_linux_gcc_target_options method.") made ppc64 return an empty
>> string from gdbarch_gcc_target_options, overriding the
>> "-mcmodel=large" that default_gcc_target_options supplies for 64-bit
>> targets, so GCC falls back to -mcmodel=medium.
> I can see why large model is more appropriate for this type
> of compilation.  However, your patch just reverts the effect
> of the above commit, without actually reverting it.  (This
> causes ppc64_linux_gcc_target_options to pretty much duplicate
> default_gcc_target_options.)  I think it would be preferable
> to fully revert the commit instead.
>
> Bye,
> Ulrich
  

Patch

diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 1d54b72bb1d..67f31e7b308 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -2081,7 +2081,7 @@  ppc64_gnu_triplet_regexp (struct gdbarch *gdbarch)
 static std::string
 ppc64_linux_gcc_target_options (struct gdbarch *gdbarch)
 {
-  return "";
+  return "-mcmodel=large";
 }
 
 /* Fetch and return the TLS DTV (dynamic thread vector) address for PTID.