[Bug compile/34456] New: ppc64le: "compile" command corrupts addresses of inferior symbols (-mcmodel=medium TOC16 relocation overflow)

abhay at sourceware dot org via Gdb-prs <[email protected]>
Newsgroups gmane.comp.gdb.bugs.discuss
Message-ID <[email protected]/bugzilla/>
https://sourceware.org/bugzilla/show_bug.cgi?id=34456

            Bug ID: 34456
           Summary: ppc64le: "compile" command corrupts addresses of
                    inferior symbols (-mcmodel=medium TOC16 relocation
                    overflow)
           Product: gdb
           Version: HEAD
            Status: NEW
          Severity: normal
          Priority: P2
         Component: compile
          Assignee: unassigned at sourceware dot org
          Reporter: abhay at sourceware dot org
  Target Milestone: ---

On ppc64le, the "compile" command generates code that stores a
corrupted address whenever the compiled expression takes the address
of a symbol in the inferior.  Calling through such an address makes
the inferior jump to unmapped memory and receive SIGSEGV.

Reproducer (pmf.cc):

  struct A { int x; int get (int i); };
  int A::get (int i) { return x + i; }
  typedef int (A::*PMF) (int);
  int main () {
    A a; a.x = 5;
    PMF pmf = &A::get;
    int var = (a.*pmf) (1);
    var = 1;              /* break here */
    return var;
  }

  $ g++ -g -O0 pmf.cc -o pmf
  $ gdb -q -batch \
      -ex "break 18" -ex run \
      -ex "info address A::get" \
      -ex "compile code pmf = &A::get" \
      -ex "x/2gx &pmf" \
      ./pmf

  Symbol "A::get(int)" is a function at address 0x1000067c.
  0x7fffffffebe8:  0x000080001000067c  0x0000000000000000

Expected: pmf holds 0x000000001000067c.
Actual:   pmf holds 0x000080001000067c -- the low 32 bits are
correct but bit 47 is wrongly set.  Adding "-ex continue" so the
program calls through pmf gives:

  Program received signal SIGSEGV, Segmentation fault.
  0x000080001000067c in ?? ()

Analysis:

ppc64_linux_gcc_target_options() returns "", which overrides the
"-mcmodel=large" that default_gcc_target_options() supplies for
64-bit targets, so the injected object is compiled with
-mcmodel=medium.  Addresses of inferior symbols are then compiled as
TOC-relative accesses using R_PPC64_TOC16_HA/LO relocations, whose
displacement is a signed 32-bit value (+/- 2GB).

GDB mmaps the compiled module in the high mmap region (e.g. around
0x7ffff7f30000) while the inferior's 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 truncated to
32 bits and the resulting address is off by 2^47.

BFD reports this via the reloc_overflow link callback, but
gdb/compile/compile-object-load.c installs an empty
link_callbacks_reloc_overflow(), so the overflow is discarded and the
truncated bytes are written into the inferior with no diagnostic.

This was introduced by commit 533f04079c7 ("[gdb] [rs6000] Add
ppc64_linux_gcc_target_options method."), which switched ppc64 from
the default large code model to medium.

Compiling the injected code with -mcmodel=large avoids the problem:
GCC then emits a real .toc section and loads addresses as full 64-bit
values, so the only TOC-relative references are into the module's own
.toc, which is always in range.  x86-64 is unaffected (no TOC); the
same test stores the correct address there.

In-tree this reproduces as failures in
gdb.compile/compile-cplus-method.exp:

  FAIL: gdb.compile/compile-cplus-method.exp: result of compile code \
    pmf = &A::get_var1; var = (a->*pmf) (2); pmf = &A::get_var
  FAIL: gdb.compile/compile-cplus-method.exp: result of compile code \
    (a->**pmf_p) (1)
  FAIL: gdb.compile/compile-cplus-method.exp: compile print \
    (a->**pmf_p) (1)

Environment: powerpc64le-linux, Fedora, GCC 15.2.1, glibc 2.42.
Reproduced on GDB 18.0.50 (git); also observed across two builds two
months apart and under the distribution's system GDB.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.