|
From: Paul F. <pa...@so...> - 2021-10-09 13:02:01
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=68bb7c063f71631a4f207adca2235eb0f8d00d33 commit 68bb7c063f71631a4f207adca2235eb0f8d00d33 Author: Paul Floyd <pj...@wa...> Date: Sat Oct 9 15:01:08 2021 +0200 FreeBSD support, patch 12 coregrind modified files Diff: --- NEWS | 20 +- coregrind/m_aspacemgr/aspacemgr-common.c | 76 +++++- coregrind/m_aspacemgr/aspacemgr-linux.c | 195 ++++++++++++- coregrind/m_aspacemgr/priv_aspacemgr.h | 2 +- coregrind/m_coredump/coredump-elf.c | 79 +++++- coregrind/m_debuginfo/d3basics.c | 4 +- coregrind/m_debuginfo/debuginfo.c | 19 +- coregrind/m_debuginfo/priv_readpdb.h | 4 +- coregrind/m_debuginfo/readdwarf.c | 8 +- coregrind/m_debuginfo/readdwarf3.c | 4 +- coregrind/m_debuginfo/readelf.c | 116 +++++++- coregrind/m_debuginfo/readpdb.c | 4 +- coregrind/m_debuginfo/storage.c | 7 +- coregrind/m_debuglog.c | 83 ++++++ coregrind/m_gdbserver/gdb/signals.h | 3 + coregrind/m_gdbserver/remote-utils.c | 37 ++- coregrind/m_gdbserver/signals.c | 8 + coregrind/m_libcassert.c | 6 +- coregrind/m_libcfile.c | 141 ++++++++-- coregrind/m_libcprint.c | 2 +- coregrind/m_libcproc.c | 108 +++++++- coregrind/m_libcsetjmp.c | 22 +- coregrind/m_libcsignal.c | 39 ++- coregrind/m_machine.c | 17 +- coregrind/m_main.c | 148 +++++++++- coregrind/m_redir.c | 5 + coregrind/m_replacemalloc/vg_replace_malloc.c | 379 +++++++++++++++++++++++--- coregrind/m_scheduler/scheduler.c | 5 +- coregrind/m_scheduler/sema.c | 4 +- coregrind/m_sigframe/sigframe-common.c | 2 +- coregrind/m_signals.c | 99 ++++++- coregrind/m_stacktrace.c | 35 ++- coregrind/m_syscall.c | 130 +++++++++ coregrind/m_syswrap/priv_types_n_macros.h | 84 +++++- coregrind/m_syswrap/syswrap-generic.c | 73 ++++- coregrind/m_syswrap/syswrap-main.c | 357 +++++++++++++++++++++++- coregrind/m_trampoline.S | 68 +++++ coregrind/m_translate.c | 4 +- coregrind/m_ume/elf.c | 14 +- coregrind/m_ume/main.c | 2 +- coregrind/m_ume/priv_ume.h | 4 +- coregrind/m_vki.c | 4 +- coregrind/m_vkiscnums.c | 11 + coregrind/pub_core_aspacemgr.h | 4 + coregrind/pub_core_debuginfo.h | 2 +- coregrind/pub_core_gdbserver.h | 1 + coregrind/pub_core_initimg.h | 2 +- coregrind/pub_core_libcproc.h | 7 + coregrind/pub_core_machine.h | 4 +- coregrind/pub_core_mallocfree.h | 2 + coregrind/pub_core_sigframe.h | 6 +- coregrind/pub_core_syscall.h | 2 + coregrind/pub_core_syswrap.h | 4 + coregrind/pub_core_trampoline.h | 8 + coregrind/vg_preloaded.c | 6 +- coregrind/vgdb.c | 2 + include/pub_tool_libcproc.h | 2 +- 57 files changed, 2270 insertions(+), 214 deletions(-) diff --git a/NEWS b/NEWS index 68315a77ad..e5414c02b4 100644 --- a/NEWS +++ b/NEWS @@ -4,8 +4,9 @@ Release 3.??.? (?? 2021) This release supports X86/Linux, AMD64/Linux, ARM32/Linux, ARM64/Linux, PPC32/Linux, PPC64BE/Linux, PPC64LE/Linux, S390X/Linux, MIPS32/Linux, MIPS64/Linux, ARM/Android, ARM64/Android, MIPS32/Android, X86/Android, -X86/Solaris, AMD64/Solaris and AMD64/MacOSX 10.12. There is also preliminary -support for X86/macOS 10.13, AMD64/macOS 10.13 and nanoMIPS/Linux. +X86/Solaris, AMD64/Solaris, AMD64/MacOSX 10.12, X86/FreeBSD and +AMD64/FreeBSD. There is also preliminary support for X86/macOS 10.13, +AMD64/macOS 10.13 and nanoMIPS/Linux. * ==================== CORE CHANGES =================== @@ -25,6 +26,8 @@ support for X86/macOS 10.13, AMD64/macOS 10.13 and nanoMIPS/Linux. - ISA 3.0 support for the darn instruction added. - ISA 3.0 support for the vector system call instruction scv added. - ISA 3.0 support for the copy, paste and cpabort instructions added. + +* Support for X86/FreeBSD and AMD64/FreeBSD has been added. * ==================== TOOL CHANGES ==================== @@ -56,6 +59,19 @@ are not entered into bugzilla tend to get forgotten about or ignored. 439590 glibc-2.34 breaks suppressions against obj:*/lib*/libc-2.*so* 440670 unhandled ppc64le-linux syscall: 252 (statfs64) and 253 (fstatfs64) 432387 s390x: z15 instructions support +439046 valgrind is unusably large when linked with lld +433437 FreeBSD support, part 1 +433438 FreeBSD support, part 2 +433439 FreeBSD support, part 3 +433469 FreeBSD support, part 4 +433473 FreeBSD support, part 5 +433477 FreeBSD support, part 6 +433479 FreeBSD support, part 7 +433504 FreeBSD support, part 8 +433506 FreeBSD support, part 9 +433507 FreeBSD support, part 10 +433508 FreeBSD support, part 11 +433510 FreeBSD support, part 12 440906 Fix impossible constraint issue in P10 testcase. 441512 Remove a unneeded / unnecessary prefix check. 441534 Update the expected output for test_isa_3_1_VRT. diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c index 214b54a35e..6814410c09 100644 --- a/coregrind/m_aspacemgr/aspacemgr-common.c +++ b/coregrind/m_aspacemgr/aspacemgr-common.c @@ -35,6 +35,7 @@ ************************************************************* */ #include "priv_aspacemgr.h" +#include "pub_core_libcassert.h" #include "config.h" @@ -171,6 +172,16 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr start, SizeT length, UInt prot, } res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, prot, flags, (UInt)fd, offset); +# elif defined(VGP_x86_freebsd) + if (flags & VKI_MAP_ANONYMOUS && fd == 0) + fd = -1; + res = VG_(do_syscall7)(__NR_mmap, (UWord)start, length, + prot, flags, fd, offset, offset >> 32ul); +# elif defined(VGP_amd64_freebsd) + if ((flags & VKI_MAP_ANONYMOUS) && fd == 0) + fd = -1; + res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, + prot, flags, fd, offset); # elif defined(VGP_x86_solaris) /* MAP_ANON with fd==0 is EINVAL. */ if (fd == 0 && (flags & VKI_MAP_ANONYMOUS)) @@ -255,7 +266,7 @@ SysRes ML_(am_open) ( const HChar* pathname, Int flags, Int mode ) /* ARM64 wants to use __NR_openat rather than __NR_open. */ SysRes res = VG_(do_syscall4)(__NR_openat, VKI_AT_FDCWD, (UWord)pathname, flags, mode); -# elif defined(VGO_linux) || defined(VGO_darwin) +# elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) SysRes res = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode); # elif defined(VGO_solaris) SysRes res = VG_(do_syscall4)(__NR_openat, VKI_AT_FDCWD, (UWord)pathname, @@ -283,7 +294,7 @@ Int ML_(am_readlink)(const HChar* path, HChar* buf, UInt bufsiz) # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path, (UWord)buf, bufsiz); -# elif defined(VGO_linux) || defined(VGO_darwin) +# elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz); # elif defined(VGO_solaris) res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path, @@ -296,7 +307,7 @@ Int ML_(am_readlink)(const HChar* path, HChar* buf, UInt bufsiz) Int ML_(am_fcntl) ( Int fd, Int cmd, Addr arg ) { -# if defined(VGO_linux) || defined(VGO_solaris) +# if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd) # if defined(VGP_nanomips_linux) SysRes res = VG_(do_syscall3)(__NR_fcntl64, fd, cmd, arg); # else @@ -330,7 +341,8 @@ Bool ML_(am_get_fd_d_i_m)( Int fd, *mode = (UInt)bufx.stx_mode; return True; } -# endif +# endif // VGO_linux only + # if defined(VGO_linux) && defined(__NR_fstat64) /* fstat64 is second candidate as it can cope with minor and major device numbers outside the 0-255 range and it works properly for x86 @@ -343,7 +355,8 @@ Bool ML_(am_get_fd_d_i_m)( Int fd, *mode = (UInt) buf64.st_mode; return True; } -# endif +# endif // VGO_linux and defined __NR_fstat64 + # if defined(__NR_fstat) struct vki_stat buf; res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf); @@ -353,7 +366,7 @@ Bool ML_(am_get_fd_d_i_m)( Int fd, *mode = (UInt) buf.st_mode; return True; } -# endif +# endif // defined __NR_fstat return False; # elif defined(VGO_solaris) # if defined(VGP_x86_solaris) @@ -372,11 +385,30 @@ Bool ML_(am_get_fd_d_i_m)( Int fd, return True; } return False; +# elif defined(VGO_freebsd) + struct vki_freebsd11_stat buf; +#if (FREEBSD_VERS >= FREEBSD_12) + SysRes res = VG_(do_syscall2)(__NR_freebsd11_fstat, fd, (UWord)&buf); +#else + SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf); +#endif + if (!sr_isError(res)) { + *dev = (ULong)buf.st_dev; + *ino = (ULong)buf.st_ino; + *mode = (UInt) buf.st_mode; + return True; + } + return False; # else # error Unknown OS # endif } +#if defined(VGO_freebsd) +#define M_FILEDESC_BUF 1000000 +static Char filedesc_buf[M_FILEDESC_BUF]; +#endif + Bool ML_(am_resolve_filename) ( Int fd, /*OUT*/HChar* buf, Int nbuf ) { #if defined(VGO_linux) @@ -389,6 +421,38 @@ Bool ML_(am_resolve_filename) ( Int fd, /*OUT*/HChar* buf, Int nbuf ) else return False; +#elif defined(VGO_freebsd) + Int mib[4]; + SysRes sres; + vki_size_t len; + Char *bp, *eb; + struct vki_kinfo_file *kf; + + mib[0] = VKI_CTL_KERN; + mib[1] = VKI_KERN_PROC; + mib[2] = VKI_KERN_PROC_FILEDESC; + mib[3] = sr_Res(VG_(do_syscall0)(__NR_getpid)); + len = sizeof(filedesc_buf); + sres = VG_(do_syscall6)(__NR___sysctl, (UWord)mib, 4, (UWord)filedesc_buf, + (UWord)&len, 0, 0); + if (sr_isError(sres)) { + VG_(debugLog)(0, "sysctl(kern.proc.filedesc)", "%s\n", VG_(strerror)(sr_Err(sres))); + ML_(am_exit)(1); + } + /* Walk though the list. */ + bp = filedesc_buf; + eb = filedesc_buf + len; + while (bp < eb) { + kf = (struct vki_kinfo_file *)bp; + if (kf->kf_fd == fd) + break; + bp += kf->kf_structsize; + } + if (bp >= eb || *kf->kf_path == '\0') + VG_(strncpy)( buf, "[unknown]", nbuf ); + else + VG_(strncpy)( buf, kf->kf_path, nbuf ); + return True; #elif defined(VGO_darwin) HChar tmp[VKI_MAXPATHLEN+1]; if (0 == ML_(am_fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) { diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c index 0eb3143161..9a69f3850f 100644 --- a/coregrind/m_aspacemgr/aspacemgr-linux.c +++ b/coregrind/m_aspacemgr/aspacemgr-linux.c @@ -4,7 +4,7 @@ /*--- The address space manager: segment initialisation and ---*/ /*--- tracking, stack operations ---*/ /*--- ---*/ -/*--- Implementation for Linux (and Darwin!) aspacemgr-linux.c ---*/ +/*--- Implementation for Linux, Darwin, Solaris and FreeBSD ---*/ /*--------------------------------------------------------------------*/ /* @@ -30,7 +30,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) /* ************************************************************* DO NOT INCLUDE ANY OTHER FILES HERE. @@ -314,6 +314,8 @@ Addr VG_(clo_aspacem_minAddr) # endif #elif defined(VGO_solaris) = (Addr) 0x00100000; // 1MB +#elif defined(VGO_freebsd) + = (Addr) 0x04000000; // 64M #else #endif @@ -367,7 +369,12 @@ static void parse_procselfmaps ( # define ARM_LINUX_FAKE_COMMPAGE_END1 0xFFFF1000 #endif - +#if !defined(VKI_MAP_STACK) +/* this is only defined for FreeBSD + * for readability, define it to 0 + * for other platforms */ +#define VKI_MAP_STACK 0 +#endif /*-----------------------------------------------------------------*/ /*--- ---*/ @@ -871,7 +878,7 @@ static void sync_check_mapping_callback ( Addr addr, SizeT len, UInt prot, cmp_devino = False; #endif -#if defined(VGO_darwin) +#if defined(VGO_darwin) || defined(VGO_freebsd) // GrP fixme kernel info doesn't have dev/inode cmp_devino = False; @@ -1491,7 +1498,13 @@ static void init_nsegment ( /*OUT*/NSegment* seg ) seg->mode = 0; seg->offset = 0; seg->fnIdx = -1; - seg->hasR = seg->hasW = seg->hasX = seg->hasT = seg->isCH = False; + + seg->hasR = seg->hasW = seg->hasX = seg->hasT + = seg->isCH = False; +#if defined(VGO_freebsd) + seg->isFF = False; +#endif + } /* Make an NSegment which holds a reservation. */ @@ -1637,6 +1650,81 @@ Addr VG_(am_startup) ( Addr sp_at_startup ) suggested_clstack_end = -1; // ignored; Mach-O specifies its stack + // --- Freebsd ------------------------------------------ +#elif defined(VGO_freebsd) + + + VG_(debugLog)(2, "aspacem", + " sp_at_startup = 0x%010lx (supplied)\n", + sp_at_startup ); + +# if VG_WORDSIZE == 4 + + aspacem_maxAddr = VG_PGROUNDDN( sp_at_startup ) - 1; +# else + aspacem_maxAddr = (Addr) (Addr)0x800000000UL - 1; // 32G +# ifdef ENABLE_INNER + { Addr cse = VG_PGROUNDDN( sp_at_startup ) - 1; + if (aspacem_maxAddr > cse) + aspacem_maxAddr = cse; + } +# endif // ENABLE_INNER +# endif + + aspacem_cStart = aspacem_minAddr; + aspacem_vStart = VG_PGROUNDUP((aspacem_minAddr + aspacem_maxAddr + 1) / 2); + +# ifdef ENABLE_INNER + aspacem_vStart -= 0x10000000UL; // 512M +# endif // ENABLE_INNER + + // starting with FreeBSD 10.4, the stack is created with a zone + // that is marked MAP_GUARD. This zone is reserved but unmapped, + // and fills the space up to the end of the segment + // see man mmap + + // Version number from + // https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/versions-10.html + + // On x86 this is 0x3FE0000 + // And on amd64 it is 0x1FFE0000 (536739840) + // There is less of an issue on amd64 as we just choose some arbitrary address rather then trying + // to squeeze in just below the host stack + + // Some of this is in sys/vm/vm_map.c, for instance vm_map_stack and vm_map_stack_locked + // These refer to the kernel global sgrowsiz, which seems to be the initial size + // of the user stack, 128k on my system + // + // This seems to be in the sysctl kern.sgrowsiz + // Then there is kern.maxssiz which is the total stack size (grow size + guard area) + // In other words guard area = maxssiz - sgrowsiz + +#if (__FreeBSD_version >= 1003516) + +#if 0 + // this block implements what is described above + // this makes no changes to the regression tests + // I'm keeping it for a rainy day. + // note this needs + // #include "pub_core_libcproc.h" + SizeT kern_maxssiz; + SizeT kern_sgrowsiz; + SizeT sysctl_size = sizeof(SizeT); + VG_(sysctlbyname)("kern.maxssiz", &kern_maxssiz, &sysctl_size, NULL, 0); + VG_(sysctlbyname)("kern.sgrowsiz", &kern_sgrowsiz, &sysctl_size, NULL, 0); + + suggested_clstack_end = aspacem_maxAddr - (kern_maxssiz - kern_sgrowsiz) + VKI_PAGE_SIZE; +#endif + + suggested_clstack_end = aspacem_maxAddr - 64*1024*1024UL + + VKI_PAGE_SIZE; + +#else + suggested_clstack_end = aspacem_maxAddr - 16*1024*1024UL + + VKI_PAGE_SIZE; + +#endif + // --- Solaris ------------------------------------------ #elif defined(VGO_solaris) # if VG_WORDSIZE == 4 @@ -1759,7 +1847,7 @@ Addr VG_(am_startup) ( Addr sp_at_startup ) suggested_clstack_end = aspacem_maxAddr - 16*1024*1024ULL + VKI_PAGE_SIZE; -#endif +#endif /* #else of 'defined(VGO_solaris)' */ // --- (end) -------------------------------------------- aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_minAddr)); @@ -2165,13 +2253,13 @@ VG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags, needDiscard = any_Ts_in_range( a, len ); init_nsegment( &seg ); - seg.kind = (flags & VKI_MAP_ANONYMOUS) ? SkAnonC : SkFileC; + seg.kind = (flags & (VKI_MAP_ANONYMOUS | VKI_MAP_STACK)) ? SkAnonC : SkFileC; seg.start = a; seg.end = a + len - 1; seg.hasR = toBool(prot & VKI_PROT_READ); seg.hasW = toBool(prot & VKI_PROT_WRITE); seg.hasX = toBool(prot & VKI_PROT_EXEC); - if (!(flags & VKI_MAP_ANONYMOUS)) { + if (!(flags & (VKI_MAP_ANONYMOUS | VKI_MAP_STACK))) { // Nb: We ignore offset requests in anonymous mmaps (see bug #126722) seg.offset = offset; if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) { @@ -2182,6 +2270,9 @@ VG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags, if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) { seg.fnIdx = ML_(am_allocate_segname)( buf ); } +#if defined(VGO_freebsd) + seg.isFF = (flags & VKI_MAP_FIXED); +#endif } add_segment( &seg ); AM_SANITY_CHECK; @@ -2423,6 +2514,9 @@ SysRes VG_(am_mmap_named_file_fixed_client_flags) } else if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) { seg.fnIdx = ML_(am_allocate_segname)( buf ); } +#if defined(VGO_freebsd) + seg.isFF = (flags & VKI_MAP_FIXED); +#endif add_segment( &seg ); AM_SANITY_CHECK; @@ -2733,6 +2827,9 @@ static SysRes VG_(am_mmap_file_float_valgrind_flags) ( SizeT length, UInt prot, if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) { seg.fnIdx = ML_(am_allocate_segname)( buf ); } +#if defined(VGO_freebsd) + seg.isFF = (flags & VKI_MAP_FIXED); +#endif add_segment( &seg ); AM_SANITY_CHECK; @@ -3796,13 +3893,89 @@ Bool VG_(get_changed_segments)( return !css_overflowed; } -#endif // defined(VGO_darwin) /*------END-procmaps-parser-for-Darwin---------------------------*/ +/*------BEGIN-procmaps-parser-for-Freebsd------------------------*/ +#elif defined(VGO_freebsd) + +/* Size of a smallish table used to read /proc/self/map entries. */ +#define M_PROCMAP_BUF 10485760 /* 10M */ + +/* static ... to keep it out of the stack frame. */ +static char procmap_buf[M_PROCMAP_BUF]; + +static void parse_procselfmaps ( + void (*record_mapping)( Addr addr, SizeT len, UInt prot, + ULong dev, ULong ino, Off64T offset, + const HChar* filename ), + void (*record_gap)( Addr addr, SizeT len ) + ) +{ + Addr start, endPlusOne, gapStart; + char* filename; + char *p; + UInt prot; + ULong foffset, dev, ino; + struct vki_kinfo_vmentry *kve; + vki_size_t len; + Int oid[4]; + SysRes sres; + + foffset = ino = 0; /* keep gcc-4.1.0 happy */ + + oid[0] = VKI_CTL_KERN; + oid[1] = VKI_KERN_PROC; + oid[2] = VKI_KERN_PROC_VMMAP; + oid[3] = sr_Res(VG_(do_syscall0)(__NR_getpid)); + len = sizeof(procmap_buf); + + sres = VG_(do_syscall6)(__NR___sysctl, (UWord)oid, 4, (UWord)procmap_buf, + (UWord)&len, 0, 0); + if (sr_isError(sres)) { + VG_(debugLog)(0, "procselfmaps", "sysctl %lu\n", sr_Err(sres)); + ML_(am_exit)(1); + } + gapStart = Addr_MIN; + p = procmap_buf; + while (p < (char *)procmap_buf + len) { + kve = (struct vki_kinfo_vmentry *)p; + start = (UWord)kve->kve_start; + endPlusOne = (UWord)kve->kve_end; + foffset = kve->kve_offset; + filename = kve->kve_path; + dev = kve->kve_fsid; + ino = kve->kve_fileid; + if (filename[0] != '/') { + filename = NULL; + foffset = 0; + } + + prot = 0; + if (kve->kve_protection & VKI_KVME_PROT_READ) prot |= VKI_PROT_READ; + if (kve->kve_protection & VKI_KVME_PROT_WRITE) prot |= VKI_PROT_WRITE; + if (kve->kve_protection & VKI_KVME_PROT_EXEC) prot |= VKI_PROT_EXEC; + + if (record_gap && gapStart < start) + (*record_gap) ( gapStart, start-gapStart ); + + if (record_mapping && start < endPlusOne) + (*record_mapping) ( start, endPlusOne-start, + prot, dev, ino, + foffset, filename ); + gapStart = endPlusOne; + p += kve->kve_structsize; + } + + if (record_gap && gapStart < Addr_MAX) + (*record_gap) ( gapStart, Addr_MAX - gapStart + 1 ); +} + +/*------END-procmaps-parser-for-Freebsd--------------------------*/ + /*------BEGIN-procmaps-parser-for-Solaris------------------------*/ -#if defined(VGO_solaris) +#elif defined(VGO_solaris) /* Note: /proc/self/xmap contains extended information about already materialized mappings whereas /proc/self/rmap contains information about @@ -4112,7 +4285,7 @@ Bool VG_(am_search_for_new_segment)(Addr *addr, SizeT *size, UInt *prot) /*------END-procmaps-parser-for-Solaris--------------------------*/ -#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff --git a/coregrind/m_aspacemgr/priv_aspacemgr.h b/coregrind/m_aspacemgr/priv_aspacemgr.h index fbc46aca7b..161c5c2954 100644 --- a/coregrind/m_aspacemgr/priv_aspacemgr.h +++ b/coregrind/m_aspacemgr/priv_aspacemgr.h @@ -77,7 +77,7 @@ extern void ML_(am_assert_fail) ( const HChar* expr, const HChar* fn ); #define aspacem_assert(expr) \ - ((void) (LIKELY(expr) ? 0 : \ + ((void) (LIKELY(expr) ? (void)0 : \ (ML_(am_assert_fail)(#expr, \ __FILE__, __LINE__, \ __PRETTY_FUNCTION__)))) diff --git a/coregrind/m_coredump/coredump-elf.c b/coregrind/m_coredump/coredump-elf.c index daf85e6479..d0e8a03c94 100644 --- a/coregrind/m_coredump/coredump-elf.c +++ b/coregrind/m_coredump/coredump-elf.c @@ -26,7 +26,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) #include "pub_core_basics.h" #include "pub_core_vki.h" @@ -90,6 +90,9 @@ static void fill_ehdr(ESZ(Ehdr) *ehdr, Int num_phdrs) ehdr->e_ident[EI_CLASS] = VG_ELF_CLASS; ehdr->e_ident[EI_DATA] = VG_ELF_DATA2XXX; ehdr->e_ident[EI_VERSION] = EV_CURRENT; +#if defined(VGO_freebsd) + ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; +#endif ehdr->e_type = ET_CORE; ehdr->e_machine = VG_ELF_MACHINE; @@ -193,6 +196,19 @@ static void write_note(Int fd, const struct note *n) VG_(write)(fd, &n->note, note_size(n)); } +#if defined(VGO_freebsd) +static void fill_prpsinfo(const ThreadState *tst, + struct vki_elf_prpsinfo *prpsinfo) +{ + VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo)); + + prpsinfo->pr_version = VKI_PRPSINFO_VERSION; + prpsinfo->pr_psinfosz = sizeof(struct vki_elf_prpsinfo); + VG_(client_fname)(prpsinfo->pr_fname, sizeof(prpsinfo->pr_fname), False); + // why? + VG_(strncpy)(prpsinfo->pr_psargs, prpsinfo->pr_fname, sizeof(prpsinfo->pr_psargs) - 1); +} +#else static void fill_prpsinfo(const ThreadState *tst, struct vki_elf_prpsinfo *prpsinfo) { @@ -223,6 +239,7 @@ static void fill_prpsinfo(const ThreadState *tst, VG_(client_fname)(prpsinfo->pr_fname, sizeof(prpsinfo->pr_fname), False); } +#endif static void fill_prstatus(const ThreadState *tst, /*OUT*/struct vki_elf_prstatus *prs, @@ -238,6 +255,16 @@ static void fill_prstatus(const ThreadState *tst, VG_(memset)(prs, 0, sizeof(*prs)); +#if defined(VGO_freebsd) + prs->pr_version = VKI_PRSTATUS_VERSION; + prs->pr_statussz = sizeof(struct vki_elf_prstatus); + prs->pr_gregsetsz = sizeof(vki_elf_gregset_t); + prs->pr_fpregsetsz = sizeof(vki_elf_fpregset_t); + prs->pr_osreldate = VG_(getosreldate)(); + + prs->pr_cursig = si->si_signo; + prs->pr_pid = tst->os_state.lwpid; +#else prs->pr_info.si_signo = si->si_signo; prs->pr_info.si_code = si->si_code; prs->pr_info.si_errno = 0; @@ -248,6 +275,7 @@ static void fill_prstatus(const ThreadState *tst, prs->pr_ppid = 0; prs->pr_pgrp = VG_(getpgrp)(); prs->pr_sid = VG_(getpgrp)(); +#endif #if defined(VGP_s390x_linux) /* prs->pr_reg has struct type. Need to take address. */ @@ -461,6 +489,45 @@ static void fill_prstatus(const ThreadState *tst, regs[VKI_MIPS32_EF_CP0_STATUS] = arch->vex.guest_CP0_status; regs[VKI_MIPS32_EF_CP0_EPC] = arch->vex.guest_PC; # undef DO +#elif defined(VGP_amd64_freebsd) + regs->rflags = LibVEX_GuestAMD64_get_rflags( &((ThreadArchState*)arch)->vex ); + regs->rsp = arch->vex.guest_RSP; + regs->rip = arch->vex.guest_RIP; + regs->rbx = arch->vex.guest_RBX; + regs->rcx = arch->vex.guest_RCX; + regs->rdx = arch->vex.guest_RDX; + regs->rsi = arch->vex.guest_RSI; + regs->rdi = arch->vex.guest_RDI; + regs->rbp = arch->vex.guest_RBP; + regs->rax = arch->vex.guest_RAX; + regs->r8 = arch->vex.guest_R8; + regs->r9 = arch->vex.guest_R9; + regs->r10 = arch->vex.guest_R10; + regs->r11 = arch->vex.guest_R11; + regs->r12 = arch->vex.guest_R12; + regs->r13 = arch->vex.guest_R13; + regs->r14 = arch->vex.guest_R14; + regs->r15 = arch->vex.guest_R15; +#elif defined(VGP_x86_freebsd) + regs->eflags = LibVEX_GuestX86_get_eflags( &arch->vex ); + regs->esp = arch->vex.guest_ESP; + regs->eip = arch->vex.guest_EIP; + + regs->ebx = arch->vex.guest_EBX; + regs->ecx = arch->vex.guest_ECX; + regs->edx = arch->vex.guest_EDX; + regs->esi = arch->vex.guest_ESI; + regs->edi = arch->vex.guest_EDI; + regs->ebp = arch->vex.guest_EBP; + regs->eax = arch->vex.guest_EAX; + + regs->cs = arch->vex.guest_CS; + regs->ds = arch->vex.guest_DS; + regs->ss = arch->vex.guest_SS; + regs->es = arch->vex.guest_ES; + regs->fs = arch->vex.guest_FS; + regs->gs = arch->vex.guest_GS; + #else # error Unknown ELF platform #endif @@ -587,6 +654,16 @@ static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu) # undef DO #elif defined(VGP_nanomips_linux) +#elif defined(VGP_x86_freebsd) + +#elif defined(VGP_amd64_freebsd) + +# define DO(n) VG_(memcpy)(fpu->xmm_space + n * 4, \ + &arch->vex.guest_YMM##n[0], 16) + DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); + DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); +# undef DO + #else # error Unknown ELF platform #endif diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c index 1bc5f8f052..555e1e00d0 100644 --- a/coregrind/m_debuginfo/d3basics.c +++ b/coregrind/m_debuginfo/d3basics.c @@ -498,11 +498,11 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, const RegSummary* regs ) { vg_assert(regs); # if defined(VGP_x86_linux) || defined(VGP_x86_darwin) \ - || defined(VGP_x86_solaris) + || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd) if (regno == 5/*EBP*/) { *a = regs->fp; return True; } if (regno == 4/*ESP*/) { *a = regs->sp; return True; } # elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) \ - || defined(VGP_amd64_solaris) + || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd) if (regno == 6/*RBP*/) { *a = regs->fp; return True; } if (regno == 7/*RSP*/) { *a = regs->sp; return True; } # elif defined(VGP_ppc32_linux) diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index e2218f2668..2e5b9b0192 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -57,7 +57,7 @@ #include "priv_tytypes.h" #include "priv_storage.h" #include "priv_readdwarf.h" -#if defined(VGO_linux) || defined(VGO_solaris) +#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd) # include "priv_readelf.h" # include "priv_readdwarf3.h" # include "priv_readpdb.h" @@ -814,7 +814,7 @@ void VG_(di_initialise) ( void ) /*--- ---*/ /*--------------------------------------------------------------*/ -#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) /* Helper (indirect) for di_notify_ACHIEVE_ACCEPT_STATE */ static Bool overlaps_DebugInfoMappings ( const DebugInfoMapping* map1, @@ -965,7 +965,7 @@ static ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di ) truncate_DebugInfoMapping_overlaps( di, di->fsm.maps ); /* And acquire new info. */ -# if defined(VGO_linux) || defined(VGO_solaris) +# if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd) ok = ML_(read_elf_debug_info)( di ); # elif defined(VGO_darwin) ok = ML_(read_macho_debug_info)( di ); @@ -1204,6 +1204,13 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd ) if (!(is_rx_map || is_rw_map || is_ro_map)) return 0; +#if defined(VGO_freebsd) + /* Ignore non-fixed read-only mappings. The dynamic linker may be + * mapping something for its own transient purposes. */ + if (!seg->isFF && is_ro_map) + return 0; +#endif + /* Peer at the first few bytes of the file, to see if it is an ELF */ /* object file. Ignore the file if we do not have read permission. */ VG_(memset)(buf1k, 0, sizeof(buf1k)); @@ -1247,7 +1254,7 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd ) vg_assert(sr_Res(preadres) > 0 && sr_Res(preadres) <= sizeof(buf1k) ); /* We're only interested in mappings of object files. */ -# if defined(VGO_linux) || defined(VGO_solaris) +# if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd) if (!ML_(is_elf_object_file)( buf1k, (SizeT)sr_Res(preadres), False )) return 0; # elif defined(VGO_darwin) @@ -1696,7 +1703,7 @@ void VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj, if (pdbname) ML_(dinfo_free)(pdbname); } -#endif /* defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) */ +#endif /* defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) */ /*------------------------------------------------------------*/ @@ -2290,6 +2297,8 @@ Vg_FnNameKind VG_(get_fnname_kind) ( const HChar* name ) VG_STREQ("generic_start_main", name) || // Yellow Dog doggedness VG_STREQN(19, "generic_start_main.", name) || // gcc optimization VG_STREQ("_start", name) || +# elif defined(VGO_freebsd) + VG_STREQ("_start", name) || // FreeBSD libc # elif defined(VGO_darwin) // See readmacho.c for an explanation of this. VG_STREQ("start_according_to_valgrind", name) || // Darwin, darling diff --git a/coregrind/m_debuginfo/priv_readpdb.h b/coregrind/m_debuginfo/priv_readpdb.h index b8f5958103..b9b8fb3a2c 100644 --- a/coregrind/m_debuginfo/priv_readpdb.h +++ b/coregrind/m_debuginfo/priv_readpdb.h @@ -30,7 +30,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) #ifndef __PRIV_READPDB_H #define __PRIV_READPDB_H @@ -57,7 +57,7 @@ HChar* ML_(find_name_of_pdb_file)( const HChar* pename ); #endif /* ndef __PRIV_READPDB_H */ -#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index bcacca4cb9..39a2946870 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -27,7 +27,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) #include "pub_core_basics.h" #include "pub_core_debuginfo.h" @@ -1961,11 +1961,11 @@ void ML_(read_debuginfo_dwarf1) ( /* --------------- Decls --------------- */ -#if defined(VGP_x86_linux) || defined(VGP_x86_solaris) +#if defined(VGP_x86_linux) || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd) # define FP_REG 5 # define SP_REG 4 # define RA_REG_DEFAULT 8 -#elif defined(VGP_amd64_linux) || defined(VGP_amd64_solaris) +#elif defined(VGP_amd64_linux) || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd) # define FP_REG 6 # define SP_REG 7 # define RA_REG_DEFAULT 16 @@ -4522,7 +4522,7 @@ void ML_(read_callframe_info_dwarf3) return; } -#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c index 4ac23a3c4d..18eecea9f3 100644 --- a/coregrind/m_debuginfo/readdwarf3.c +++ b/coregrind/m_debuginfo/readdwarf3.c @@ -33,7 +33,7 @@ without prior written permission. */ -#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) /* REFERENCE (without which this code will not make much sense): @@ -5879,7 +5879,7 @@ ML_(new_dwarf3_reader) ( TRACE_SYMTAB("\n"); #endif -#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c index e424e3e7e8..c586e3f332 100644 --- a/coregrind/m_debuginfo/readelf.c +++ b/coregrind/m_debuginfo/readelf.c @@ -27,7 +27,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_solaris) +#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd) #include "pub_core_basics.h" #include "pub_core_vki.h" @@ -45,6 +45,7 @@ #include "pub_core_syscall.h" #include "pub_core_tooliface.h" /* VG_(needs) */ #include "pub_core_xarray.h" +#include "pub_core_libcproc.h" #include "priv_misc.h" /* dinfo_zalloc/free/strdup */ #include "priv_image.h" #include "priv_d3basics.h" @@ -1118,6 +1119,80 @@ void read_elf_symtab__ppc64be_linux( VG_(OSetGen_Destroy)( oset ); } +#if defined(VGO_freebsd) + +/** + * read_and_set_osrel + * + * "osrel" is in an Elf note. It has values such as 1201000 for FreeBSD 12.1 + * Some of the behaviour related to SIGSEGV and SIGBUS signals depends on the + * kernel reading this value. + * + * However in the case of Valgrind, the host is strictly statically linked and + * does not contain the NT_FREEBSD_ABI_TAG note. And even if it did, we want to + * override the value with that of the guest. + * + * At some later date we might want to look at the value of "fctl0" (note with the + * NT_FREEBSD_FEATURE_CTL type). This seems to be related to Address Space Layout + * Randomization. No hurry at the moment. + * + * See /usr/src/sys/kern/imgact_elf.c for details on how the kernel reads these + * notes. + */ +static +void read_and_set_osrel(DiImage* img) +{ + if (is_elf_object_file_by_DiImage(img, False)) { + Word i; + + ElfXX_Ehdr ehdr; + ML_(img_get)(&ehdr, img, 0, sizeof(ehdr)); + /* Skip the phdrs when we have to search the shdrs. In separate + .debug files the phdrs might not be valid (they are a copy of + the main ELF file) and might trigger assertions when getting + image notes based on them. */ + for (i = 0; i < ehdr.e_phnum; i++) { + ElfXX_Phdr phdr; + ML_(img_get)(&phdr, img, + ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr)); + + if (phdr.p_type == PT_NOTE) { + ElfXX_Off note_ioff = phdr.p_offset; + + while (note_ioff < phdr.p_offset + phdr.p_filesz) { + ElfXX_Nhdr note[2]; + ML_(img_get)(note, img, (DiOffT)note_ioff, sizeof(note)); + DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr); + //DiOffT desc_ioff = name_ioff + ((note[0].n_namesz + 3) & ~3); + if (ML_(img_strcmp_c)(img, name_ioff, "FreeBSD") == 0 + && note[0].n_type == NT_FREEBSD_ABI_TAG) { + + u_int32_t osrel = note[1].n_type; + int name[4]; + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_OSREL; + name[3] = VG_(getpid)(); + SizeT newlen = sizeof(osrel); + Int error = VG_(sysctl)(name, 4, NULL, NULL, &osrel, newlen); + if (error == -1) { + VG_(message)(Vg_DebugMsg, "Warning: failed to set osrel for current process with value %d\n", osrel); + } else { + if (VG_(clo_verbosity) > 1) { + VG_(message)(Vg_DebugMsg, "Set osrel for current process with value %d\n", osrel); + } + } + } + note_ioff = note_ioff + sizeof(ElfXX_Nhdr) + + ((note[0].n_namesz + 3) & ~3) + + ((note[0].n_descsz + 3) & ~3); + } + } + } + } + +} +#endif /* * Look for a build-id in an ELF image. The build-id specification @@ -1701,7 +1776,7 @@ static HChar* readlink_path (const HChar *path) #if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path, (UWord)buf, bufsiz); -#elif defined(VGO_linux) || defined(VGO_darwin) +#elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz); #elif defined(VGO_solaris) res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path, @@ -1939,14 +2014,14 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); if (map->rx) - TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %ld\n", - map->avma, map->size, map->foff); + TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lld\n", + map->avma, map->size, (Long)map->foff); } for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); if (map->rw) - TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %ld\n", - map->avma, map->size, map->foff); + TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lld\n", + map->avma, map->size, (Long)map->foff); } if (phdr_mnent == 0 @@ -2039,6 +2114,11 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) item.svma_limit = a_phdr.p_vaddr + a_phdr.p_memsz; item.bias = map->avma - map->foff + a_phdr.p_offset - a_phdr.p_vaddr; +#if (FREEBSD_VERS >= FREEBSD_12_2) + if ((long long int)item.bias < 0LL) { + item.bias = 0; + } +#endif if (map->rw && (a_phdr.p_flags & (PF_R | PF_W)) == (PF_R | PF_W)) { @@ -2166,8 +2246,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); if (map->rx) - TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %lu\n", - map->avma, map->foff, map->foff + map->size - 1 ); + TRACE_SYMTAB("rx: at %#lx are mapped foffsets %lld .. %lld\n", + map->avma, (Long)map->foff, (Long)(map->foff + map->size - 1) ); } TRACE_SYMTAB("rx: contains these svma regions:\n"); for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) { @@ -2179,8 +2259,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); if (map->rw) - TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %lu\n", - map->avma, map->foff, map->foff + map->size - 1 ); + TRACE_SYMTAB("rw: at %#lx are mapped foffsets %lld .. %lld\n", + map->avma, (Long)map->foff, (Long)(map->foff + map->size - 1) ); } TRACE_SYMTAB("rw: contains these svma regions:\n"); for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) { @@ -2222,10 +2302,11 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) } } - TRACE_SYMTAB(" [sec %2ld] %s %s al%4u foff %6ld .. %6lu " + TRACE_SYMTAB(" [sec %2ld] %s %s al%4u foff %6lld .. %6lld " " svma %p name \"%s\"\n", i, inrx ? "rx" : " ", inrw ? "rw" : " ", alyn, - foff, (size == 0) ? foff : foff+size-1, (void *) svma, name); + (Long) foff, (size == 0) ? (Long)foff : (Long)(foff+size-1), + (void *) svma, name); /* Check for sane-sized segments. SHT_NOBITS sections have zero size in the file and their offsets are just conceptual. */ @@ -2540,7 +2621,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ - || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) + || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \ + || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) /* Accept .plt where mapped as rx (code) */ if (0 == VG_(strcmp)(name, ".plt")) { if (inrx && !di->plt_present) { @@ -2876,6 +2958,12 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) |dimg| to it. */ vg_assert(dimg == NULL && aimg == NULL); +#if defined(VGO_freebsd) + /* */ + read_and_set_osrel(mimg); + +#endif + /* Look for a build-id */ HChar* buildid = find_buildid(mimg, False, False); @@ -3512,7 +3600,7 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) /* NOTREACHED */ } -#endif // defined(VGO_linux) || defined(VGO_solaris) +#endif // defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff --git a/coregrind/m_debuginfo/readpdb.c b/coregrind/m_debuginfo/readpdb.c index f9128e30cf..a53cf48c44 100644 --- a/coregrind/m_debuginfo/readpdb.c +++ b/coregrind/m_debuginfo/readpdb.c @@ -33,7 +33,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) #include "pub_core_basics.h" #include "pub_core_debuginfo.h" @@ -2604,7 +2604,7 @@ HChar* ML_(find_name_of_pdb_file)( const HChar* pename ) return res; } -#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) +#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c index 48a92b4029..9ba74076c1 100644 --- a/coregrind/m_debuginfo/storage.c +++ b/coregrind/m_debuginfo/storage.c @@ -365,6 +365,11 @@ void ML_(addSym) ( struct _DebugInfo* di, DiSym* sym ) vg_assert(sym->pri_name != NULL); vg_assert(sym->sec_names == NULL); +#if defined(VGO_freebsd) + if (sym->size == 0) + sym->size = 1; +#endif + /* Ignore zero-sized syms. */ if (sym->size == 0) return; @@ -1534,7 +1539,7 @@ Bool preferName ( const DebugInfo* di, vlena = VG_(strlen)(a_name); vlenb = VG_(strlen)(b_name); -# if defined(VGO_linux) || defined(VGO_solaris) +# if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd) # define VERSION_CHAR '@' # elif defined(VGO_darwin) # define VERSION_CHAR '$' diff --git a/coregrind/m_debuglog.c b/coregrind/m_debuglog.c index ce4714d1bf..355c3caf5b 100644 --- a/coregrind/m_debuglog.c +++ b/coregrind/m_debuglog.c @@ -435,6 +435,89 @@ static UInt local_sys_getpid ( void ) return (UInt)(__res); } +#elif defined(VGP_x86_freebsd) +static UInt local_sys_write_stderr (const HChar* buf, Int n ) +{ + Int result; + + __asm__ volatile ( + "movl %2, %%eax\n" /* push n */ + "movl %1, %%edx\n" /* push buf */ + "pushl %%eax\n" + "pushl %%edx\n" + "movl $2, %%eax\n" /* push stderr */ + "pushl %%eax\n" + "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" + "pushl %%eax\n" /* push write syscall id */ + "int $0x80\n" /* write(stderr, buf, n) */ + "jnc 1f\n" /* jump if no error */ + "movl $-1, %%eax\n" /* return -1 if error */ + "1: " + "movl %%eax, %0\n" /* __res = eax */ + "addl $16, %%esp\n" /* pop x4 */ + : /*wr*/ "=mr" (result) + : /*rd*/ "g" (buf), "g" (n) + : /*trash*/ "eax", "edx", "cc" + ); + return result >= 0 ? result : -1; +} + +static UInt local_sys_getpid ( void ) +{ + UInt __res; + __asm__ volatile ( + "movl $20, %%eax\n" /* set %eax = __NR_getpid */ + "int $0x80\n" /* getpid() */ + "movl %%eax, %0\n" /* set __res = eax */ + : "=mr" (__res) + : + : "eax" ); + return __res; +} + +#elif defined(VGP_amd64_freebsd) +__attribute__((noinline)) +static UInt local_sys_write_stderr (const HChar* buf, Int n ) +{ + volatile Long block[2]; + block[0] = (Long)buf; + block[1] = n; + __asm__ volatile ( + "subq $256, %%rsp\n" /* don't trash the stack redzone */ + "pushq %%r15\n" /* r15 is callee-save */ + "movq %0, %%r15\n" /* r15 = &block */ + "pushq %%r15\n" /* save &block */ + "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */ + "movq $2, %%rdi\n" /* rdi = stderr */ + "movq 0(%%r15), %%rsi\n" /* rsi = buf */ + "movq 8(%%r15), %%rdx\n" /* rdx = n */ + "syscall\n" /* write(stderr, buf, n) */ + "popq %%r15\n" /* reestablish &block */ + "movq %%rax, 0(%%r15)\n" /* block[0] = result */ + "popq %%r15\n" /* restore r15 */ + "addq $256, %%rsp\n" /* restore stack ptr */ + : /*wr*/ + : /*rd*/ "r" (block) + : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc", "rcx", "r8", "r9", "r11" + ); + if (block[0] < 0) + block[0] = -1; + return (UInt)block[0]; +} + +static UInt local_sys_getpid ( void ) +{ + UInt __res; + __asm__ volatile ( + "movq $20, %%rax\n" /* set %rax = __NR_getpid */ + "syscall\n" /* getpid() */ + "movl %%eax, %0\n" /* set __res = %eax */ + : "=mr" (__res) + : + : "rax", "rcx");//, "r11" ); + return __res; +} + #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) static UInt local_sys_write_stderr ( const HChar* buf, Int n ) diff --git a/coregrind/m_gdbserver/gdb/signals.h b/coregrind/m_gdbserver/gdb/signals.h index d04a574771..4857475fa3 100644 --- a/coregrind/m_gdbserver/gdb/signals.h +++ b/coregrind/m_gdbserver/gdb/signals.h @@ -137,6 +137,9 @@ enum target_signal /* Used internally by Solaris threads. See signal(5) on Solaris. */ TARGET_SIGNAL_CANCEL = 76, + /* Similar to the above, but for FreeBSD */ + TARGET_SIGNAL_THR = 77, + /* Yes, this pains me, too. But LynxOS didn't have SIG32, and now GNU/Linux does, and we can't disturb the numbering, since it's part of the remote protocol. Note that in some GDB's diff --git a/coregrind/m_gdbserver/remote-utils.c b/coregrind/m_gdbserver/remote-utils.c index 2d13b79f3d..559d8dd8e9 100644 --- a/coregrind/m_gdbserver/remote-utils.c +++ b/coregrind/m_gdbserver/remote-utils.c @@ -27,6 +27,7 @@ #include "pub_core_libcsignal.h" #include "pub_core_options.h" #include "pub_core_aspacemgr.h" +#include "pub_core_syswrap.h" #include "server.h" @@ -322,7 +323,11 @@ void remote_open (const HChar *name) (Addr) VG_(threads), VG_N_THREADS, sizeof(ThreadState), offsetof(ThreadState, status), offsetof(ThreadState, os_state) + offsetof(ThreadOSstate, lwpid), - 0}; + 0 +#if VEX_HOST_WORDSIZE == 8 + , 0 +#endif + }; user = VG_(getenv)("LOGNAME"); if (user == NULL) user = VG_(getenv)("USER"); @@ -519,12 +524,30 @@ void remote_close (void) from_gdb ? from_gdb : "NULL", to_gdb ? to_gdb : "NULL", shared_mem ? shared_mem : "NULL"); - if (pid == pid_from_to_creator && from_gdb && VG_(unlink) (from_gdb) == -1) - warning ("could not unlink %s\n", from_gdb); - if (pid == pid_from_to_creator && to_gdb && VG_(unlink) (to_gdb) == -1) - warning ("could not unlink %s\n", to_gdb); - if (pid == pid_from_to_creator && shared_mem && VG_(unlink) (shared_mem) == -1) - warning ("could not unlink %s\n", shared_mem); + + // PJF this is not ideal + // if the guest enters capability mode then the unlink calls will fail + // this may well also apply to Linux and seccomp + // I don't have any thoughts on how to fix it, other than forking early on + // having the child run the guest and the parent wait()ing and then + // the parent doing the cleanup + + Bool unlinkPossible = True; +#if defined(VGO_freebsd) + unlinkPossible = (VG_(get_capability_mode)() == False); +#endif + + if (unlinkPossible == True) { + if (pid == pid_from_to_creator && from_gdb && VG_(unlink) (from_gdb) == -1) + warning ("could not unlink %s\n", from_gdb); + if (pid == pid_from_to_creator && to_gdb && VG_(unlink) (to_gdb) == -1) + warning ("could not unlink %s\n", to_gdb); + if (pid == pid_from_to_creator && shared_mem && VG_(unlink) (shared_mem) == -1) + warning ("could not unlink %s\n", shared_mem); + } else { + VG_(debugLog)(1, "remote close", + "cannot unlink gdb pipes\n"); + } free (from_gdb); from_gdb = NULL; free (to_gdb); diff --git a/coregrind/m_gdbserver/signals.c b/coregrind/m_gdbserver/signals.c index 24948a19a4..9aee90fcba 100644 --- a/coregrind/m_gdbserver/signals.c +++ b/coregrind/m_gdbserver/signals.c @@ -404,6 +404,10 @@ enum target_signal target_signal_from_host (int hostsig) if (hostsig == VKI_SIGCANCEL) return TARGET_SIGNAL_CANCEL; #endif +#if defined(VKI_SIGTHR) + if (hostsig == VKI_SIGTHR) + return TARGET_SIGNAL_THR; +#endif #if defined (VKI_SIGLWP) if (hostsig == VKI_SIGLWP) return TARGET_SIGNAL_LWP; @@ -657,6 +661,10 @@ int do_target_signal_to_host (enum target_signal oursig, case TARGET_SIGNAL_CANCEL: return VKI_SIGCANCEL; #endif +#if defined (VKI_SIGTHR) + case TARGET_SIGNAL_THR: + return VKI_SIGTHR; +#endif #if defined (VKI_SIGLWP) case TARGET_SIGNAL_LWP: return VKI_SIGLWP; diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c index ec63fccefb..35f37f88df 100644 --- a/coregrind/m_libcassert.c +++ b/coregrind/m_libcassert.c @@ -49,7 +49,7 @@ ------------------------------------------------------------------ */ #if defined(VGP_x86_linux) || defined(VGP_x86_darwin) \ - || defined(VGP_x86_solaris) + || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd) # define GET_STARTREGS(srP) \ { UInt eip, esp, ebp; \ __asm__ __volatile__( \ @@ -66,7 +66,7 @@ (srP)->misc.X86.r_ebp = ebp; \ } #elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) \ - || defined(VGP_amd64_solaris) + || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd) # define GET_STARTREGS(srP) \ { ULong rip, rsp, rbp; \ __asm__ __volatile__( \ @@ -309,7 +309,7 @@ void VG_(exit_now)( Int status ) { #if defined(VGO_linux) (void)VG_(do_syscall1)(__NR_exit_group, status ); -#elif defined(VGO_darwin) || defined(VGO_solaris) +#elif defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) (void)VG_(do_syscall1)(__NR_exit, status ); #else # error Unknown OS diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c index 3a8fed85d9..598027c6d9 100644 --- a/coregrind/m_libcfile.c +++ b/coregrind/m_libcfile.c @@ -67,6 +67,11 @@ Int VG_(safe_fd)(Int oldfd) return newfd; } +#if defined(VGO_freebsd) +#define M_FILEDESC_BUF 1000000 +static Char filedesc_buf[M_FILEDESC_BUF]; +#endif + /* Given a file descriptor, attempt to deduce its filename. To do this, we use /proc/self/fd/<FD>. If this doesn't point to a file, or if it doesn't exist, we return False. @@ -113,6 +118,46 @@ Bool VG_(resolve_filename) ( Int fd, const HChar** result ) *result = NULL; return False; +#elif defined(VGO_freebsd) + Int mib[4]; + SysRes sres; + vki_size_t len; + Char *bp, *eb; + struct vki_kinfo_file *kf; + static HChar *buf = NULL; + static SizeT bufsiz = 0; + + if (buf == NULL) { // first time + bufsiz = 500; + buf = VG_(malloc)("resolve_filename", bufsiz); + } + + mib[0] = VKI_CTL_KERN; + mib[1] = VKI_KERN_PROC; + mib[2] = VKI_KERN_PROC_FILEDESC; + mib[3] = sr_Res(VG_(do_syscall0)(__NR_getpid)); + len = sizeof(filedesc_buf); + sres = VG_(do_syscall6)(__NR___sysctl, (UWord)mib, 4, (UWord)filedesc_buf, + (UWord)&len, 0, 0); + if (sr_isError(sres)) { + VG_(debugLog)(0, "sysctl(kern.proc.filedesc)", "%s\n", VG_(strerror)(sr_Err(sres))); + return False; + } + /* Walk though the list. */ + bp = filedesc_buf; + eb = filedesc_buf + len; + while (bp < eb) { + kf = (struct vki_kinfo_file *)bp; + if (kf->kf_fd == fd) + break; + bp += kf->kf_structsize; + } + if (bp >= eb || *kf->kf_path == '\0') + VG_(strncpy)( buf, "[unknown]", bufsiz ); + else + VG_(strncpy)( buf, kf->kf_path, bufsiz ); + *result = buf; + return True; # elif defined(VGO_darwin) HChar tmp[VKI_MAXPATHLEN+1]; if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) { @@ -143,6 +188,9 @@ SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev ) # elif defined(VGO_linux) || defined(VGO_darwin) SysRes res = VG_(do_syscall3)(__NR_mknod, (UWord)pathname, mode, dev); +# elif defined(VGO_freebsd) + SysRes res = VG_(do_syscall3)(__NR_freebsd11_mknod, + (UWord)pathname, mode, dev); # elif defined(VGO_solaris) SysRes res = VG_(do_syscall4)(__NR_mknodat, VKI_AT_FDCWD, (UWord)pathname, mode, dev); @@ -158,7 +206,7 @@ SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode ) /* ARM64 wants to use __NR_openat rather than __NR_open. */ SysRes res = VG_(do_syscall4)(__NR_openat, VKI_AT_FDCWD, (UWord)pathname, flags, mode); -# elif defined(VGO_linux) +# elif defined(VGO_linux) || defined(VGO_freebsd) SysRes res = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode); # elif defined(VGO_darwin) @@ -186,7 +234,7 @@ Int VG_(fd_open) (const HChar* pathname, Int flags, Int mode) void VG_(close) ( Int fd ) { /* Hmm. Return value is not checked. That's uncool. */ -# if defined(VGO_linux) || defined(VGO_solaris) +# if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd) (void)VG_(do_syscall1)(__NR_close, fd); # elif defined(VGO_darwin) (void)VG_(do_syscall1)(__NR_close_nocancel, fd); @@ -198,7 +246,7 @@ void VG_(close) ( Int fd ) Int VG_(read) ( Int fd, void* buf, Int count) { Int ret; -# if defined(VGO_linux) || defined(VGO_solaris) +# if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd) SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count); # elif defined(VGO_darwin) SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count); @@ -218,7 +266,7 @@ Int VG_(read) ( Int fd, void* buf, Int count) Int VG_(write) ( Int fd, const void* buf, Int count) { Int ret; -# if defined(VGO_linux) || defined(VGO_solaris) +# if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd) SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count); # elif defined(VGO_darwin) SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count); @@ -254,6 +302,13 @@ Int VG_(pipe) ( Int fd[2] ) # elif defined(VGO_linux) SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd); return sr_isError(res) ? -1 : 0; +# elif defined(VGO_freebsd) + SysRes res = VG_(do_syscall0)(__NR_freebsd10_pipe); + if (!sr_isError(res)) { + fd[0] = sr_Res(res); + fd[1] = sr_ResHI(res); + } + return sr_isError(res) ? -1 : 0; # elif defined(VGO_darwin) /* __NR_pipe is UX64, so produces a double-word result */ SysRes res = VG_(do_syscall0)(__NR_pipe); @@ -281,7 +336,7 @@ Int VG_(pipe) ( Int fd[2] ) Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence ) { -# if defined(VGO_linux) || defined(VGP_amd64_darwin) +# if defined(VGO_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd) # if defined(__NR__llseek) Off64T result; SysRes res = VG_(do_syscall5)(__NR__llseek, fd, @@ -293,7 +348,7 @@ Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence ) vg_assert(sizeof(Off64T) == sizeof(sr_Res(res))); return sr_isError(res) ? (-1) : sr_Res(res); # endif -# elif defined(VGP_x86_darwin) +# elif defined(VGP_x86_darwin) || defined(VGP_x86_freebsd) SysRes res = VG_(do_syscall4)(__NR_lseek, fd, offset & 0xffffffff, offset >> 32, whence); return sr_isError(res) ? (-1) : sr_Res(res); @@ -424,6 +479,18 @@ SysRes VG_(stat) ( const HChar* file_n... [truncated message content] |