https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85988

            Bug ID: 85988
           Summary: Incorrect offset of __private_tm
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libitm
          Assignee: unassigned at gcc dot gnu.org
          Reporter: hjl.tools at gmail dot com
  Target Milestone: ---
            Target: x86-64-*-linux*

In glibc, sysdeps/i386/nptl/tls.h has

typedef struct
{
  void *tcb;            /* Pointer to the TCB.  Not necessarily the
                           thread descriptor used by libpthread.  */
  dtv_t *dtv;
  void *self;           /* Pointer to the thread descriptor.  */
  int multiple_threads;
  uintptr_t sysinfo;
  uintptr_t stack_guard;
  uintptr_t pointer_guard;
  int gscope_flag;
  int __glibc_reserved1;
  /* Reservation of some values for the TM ABI.  */
  void *__private_tm[4];
  /* GCC split stack support.  */
  void *__private_ss;
} tcbhead_t;

and sysdeps/x86_64/nptl/tls.h has


typedef struct
{
  void *tcb;            /* Pointer to the TCB.  Not necessarily the
                           thread descriptor used by libpthread.  */
  dtv_t *dtv;
  void *self;           /* Pointer to the thread descriptor.  */
  int multiple_threads;
  int gscope_flag;
  uintptr_t sysinfo;
  uintptr_t stack_guard;
  uintptr_t pointer_guard;
  unsigned long int vgetcpu_cache[2];
  int __glibc_reserved1;
  int __glibc_unused1;
  /* Reservation of some values for the TM ABI.  */
  void *__private_tm[4];
  /* GCC split stack support.  */
  void *__private_ss;
  long int __glibc_reserved2;
  /* Must be kept even if it is no longer used by glibc since programs,
     like AddressSanitizer, depend on the size of tcbhead_t.  */
  __128bits __glibc_unused2[8][4] __attribute__ ((aligned (32)));

  void *__padding[8];
} tcbhead_t;

The offsets of __private_tm are

i386:   36 bytes != 4 * 10 bytes
x32:    48 bytes != 4 * 10 btes
x86_64: 80 bytes == 8 * 10 bytes

But config/linux/x86/tls.h has

#ifdef __x86_64__
#ifdef __LP64__
# define SEG_READ(OFS)          "movq\t%%fs:(" #OFS "*8),%0"
# define SEG_WRITE(OFS)         "movq\t%0,%%fs:(" #OFS "*8)"
# define SEG_DECODE_READ(OFS)   SEG_READ(OFS) "\n\t" \
                                "rorq\t$17,%0\n\t" \
                                "xorq\t%%fs:48,%0"
# define SEG_ENCODE_WRITE(OFS)  "xorq\t%%fs:48,%0\n\t" \
                                "rolq\t$17,%0\n\t" \
                                SEG_WRITE(OFS)
#else
// For X32.
# define SEG_READ(OFS)          "movl\t%%fs:(" #OFS "*4),%0"
# define SEG_WRITE(OFS)         "movl\t%0,%%fs:(" #OFS "*4)"
# define SEG_DECODE_READ(OFS)   SEG_READ(OFS) "\n\t" \
                                "rorl\t$9,%0\n\t" \
                                "xorl\t%%fs:24,%0"
# define SEG_ENCODE_WRITE(OFS)  "xorl\t%%fs:24,%0\n\t" \
                                "roll\t$9,%0\n\t" \
                                SEG_WRITE(OFS)
#endif
#else
# define SEG_READ(OFS)  "movl\t%%gs:(" #OFS "*4),%0"
# define SEG_WRITE(OFS) "movl\t%0,%%gs:(" #OFS "*4)"
# define SEG_DECODE_READ(OFS)   SEG_READ(OFS) "\n\t" \
                                "rorl\t$9,%0\n\t" \
                                "xorl\t%%gs:24,%0"
# define SEG_ENCODE_WRITE(OFS)  "xorl\t%%gs:24,%0\n\t" \
                                "roll\t$9,%0\n\t" \
                                SEG_WRITE(OFS)
#endif

static inline struct gtm_thread *gtm_thr(void)
{
  struct gtm_thread *r;
  asm volatile (SEG_READ(10) : "=r"(r));
  return r;
}

static inline void set_gtm_thr(struct gtm_thread *x)
{
  asm volatile (SEG_WRITE(10) : : "r"(x));
}amespace GTM HIDDEN {

static inline struct abi_dispatch *abi_disp(void)
{
  struct abi_dispatch *r;
  asm volatile (SEG_DECODE_READ(11) : "=r"(r));
  return r;
}

static inline void set_abi_disp(struct abi_dispatch *x)
{
  void *scratch;
  asm volatile (SEG_ENCODE_WRITE(11) : "=r"(scratch) : "0"(x));
}

SEG_* macros are correct only for x86-64.

Reply via email to