+#ifdef PT_LWPINFO
+/* Return the size of siginfo for the current inferior. */
+
+#ifdef __LP64__
+union sigval32 {
+ int sival_int;
+ uint32_t sival_ptr;
+};
+
+/* This structure matches the naming and layout of `siginfo_t' in
+ <sys/signal.h>. In particular, the `si_foo' macros defined in that
+ header can be used with both types to copy fields in the `_reason'
+ union. */
+
+struct siginfo32
+{
+ int si_signo;
+ int si_errno;
+ int si_code;
+ __pid_t si_pid;
+ __uid_t si_uid;
+ int si_status;
+ uint32_t si_addr;
+ union sigval32 si_value;
+ union
+ {
+ struct
+ {
+ int _trapno;
+ } _fault;
+ struct
+ {
+ int _timerid;
+ int _overrun;
+ } _timer;
+ struct
+ {
+ int _mqd;
+ } _mesgq;
+ struct
+ {
+ int32_t _band;
+ } _poll;
+ struct
+ {
+ int32_t __spare1__;
+ int __spare2__[7];
+ } __spare__;
+ } _reason;
+};
+#endif
+
+static size_t
+fbsd_siginfo_size ()
+{
+#ifdef __LP64__
+ struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
+
+ /* Is the inferior 32-bit? If so, use the 32-bit siginfo size. */
+ if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+ return sizeof (struct siginfo32);
+#endif
+ return sizeof (siginfo_t);
+}
+
+/* Convert a native 64-bit siginfo object to a 32-bit object. Note
+ that FreeBSD doesn't support writing to $_siginfo, so this only
+ needs to convert one way. */
+
+static void
+fbsd_convert_siginfo (siginfo_t *si)
+{
+#ifdef __LP64__
+ struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
+
+ /* Is the inferior 32-bit? If not, nothing to do. */
+ if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word != 32)
+ return;
+
+ struct siginfo32 si32;
+
+ si32.si_signo = si->si_signo;
+ si32.si_errno = si->si_errno;
+ si32.si_code = si->si_code;
+ si32.si_pid = si->si_pid;
+ si32.si_uid = si->si_uid;
+ si32.si_status = si->si_status;
+ si32.si_addr = (uintptr_t) si->si_addr;
+
+ /* If sival_ptr is being used instead of sival_int on a big-endian
+ platform, then sival_int will be zero since it holds the upper
+ 32-bits of the pointer value. */
+#if _BYTE_ORDER == _BIG_ENDIAN
+ if (si->si_value.sival_int == 0)
+ si32.si_value.sival_ptr = (uintptr_t) si->si_value.sival_ptr;
+ else
+ si32.si_value.sival_int = si->si_value.sival_int;
+#else
+ si32.si_value.sival_int = si->si_value.sival_int;
+#endif
+
+ /* Always copy the spare fields and then possibly overwrite them for
+ signal-specific or code-specific fields. */
+ si32._reason.__spare__.__spare1__ = si->_reason.__spare__.__spare1__;
+ for (int i = 0; i < 7; i++)
+ si32._reason.__spare__.__spare2__[i] = si->_reason.__spare__.__spare2__[i];
+ switch (si->si_signo) {
+ case SIGILL:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGBUS:
+ si32.si_trapno = si->si_trapno;
+ break;
+ }
+ switch (si->si_code) {
+ case SI_TIMER:
+ si32.si_timerid = si->si_timerid;
+ si32.si_overrun = si->si_overrun;
+ break;
+ case SI_MESGQ:
+ si32.si_mqd = si->si_mqd;
+ break;
+ }
+
+ memcpy(si, &si32, sizeof (si32));
+#endif
+}
+#endif
+