16d1862363c88c183b0ed7740fca876342cf0474bStephen Hines//===-- sanitizer_procmaps_freebsd.cc -------------------------------------===//
26d1862363c88c183b0ed7740fca876342cf0474bStephen Hines//
36d1862363c88c183b0ed7740fca876342cf0474bStephen Hines//                     The LLVM Compiler Infrastructure
46d1862363c88c183b0ed7740fca876342cf0474bStephen Hines//
56d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// This file is distributed under the University of Illinois Open Source
66d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// License. See LICENSE.TXT for details.
76d1862363c88c183b0ed7740fca876342cf0474bStephen Hines//
86d1862363c88c183b0ed7740fca876342cf0474bStephen Hines//===----------------------------------------------------------------------===//
96d1862363c88c183b0ed7740fca876342cf0474bStephen Hines//
106d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// Information about the process mappings (FreeBSD-specific parts).
116d1862363c88c183b0ed7740fca876342cf0474bStephen Hines//===----------------------------------------------------------------------===//
126d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
136d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "sanitizer_platform.h"
146d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if SANITIZER_FREEBSD
156d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "sanitizer_common.h"
166d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "sanitizer_freebsd.h"
176d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "sanitizer_procmaps.h"
186d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
196d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include <unistd.h>
206d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include <sys/sysctl.h>
216d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include <sys/user.h>
226d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
236d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode.
246d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
256d1862363c88c183b0ed7740fca876342cf0474bStephen Hines# include <osreldate.h>
266d1862363c88c183b0ed7740fca876342cf0474bStephen Hines# if __FreeBSD_version <= 902001  // v9.2
276d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#  define kinfo_vmentry xkinfo_vmentry
286d1862363c88c183b0ed7740fca876342cf0474bStephen Hines# endif
296d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif
306d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
316d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesnamespace __sanitizer {
326d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
336d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  const int Mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid() };
356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  size_t Size = 0;
366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  int Err = sysctl(Mib, 4, NULL, &Size, NULL, 0);
376d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  CHECK_EQ(Err, 0);
386d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  CHECK_GT(Size, 0);
396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
406d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  size_t MmapedSize = Size * 4 / 3;
416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");
426d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  Size = MmapedSize;
436d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  Err = sysctl(Mib, 4, VmMap, &Size, NULL, 0);
446d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  CHECK_EQ(Err, 0);
456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
466d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  proc_maps->data = (char*)VmMap;
476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  proc_maps->mmaped_size = MmapedSize;
486d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  proc_maps->len = Size;
496d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
516d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
526d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                               char filename[], uptr filename_size,
536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                               uptr *protection) {
546d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  char *last = proc_self_maps_.data + proc_self_maps_.len;
556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if (current_ >= last) return false;
566d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  uptr dummy;
576d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if (!start) start = &dummy;
586d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if (!end) end = &dummy;
596d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if (!offset) offset = &dummy;
606d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if (!protection) protection = &dummy;
616d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  struct kinfo_vmentry *VmEntry = (struct kinfo_vmentry*)current_;
626d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
636d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  *start = (uptr)VmEntry->kve_start;
646d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  *end = (uptr)VmEntry->kve_end;
656d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  *offset = (uptr)VmEntry->kve_offset;
666d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
676d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  *protection = 0;
686d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if ((VmEntry->kve_protection & KVME_PROT_READ) != 0)
696d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    *protection |= kProtectionRead;
706d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0)
716d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    *protection |= kProtectionWrite;
726d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0)
736d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    *protection |= kProtectionExecute;
746d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if (filename != NULL && filename_size > 0) {
766d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    internal_snprintf(filename,
776d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                      Min(filename_size, (uptr)PATH_MAX),
786d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                      "%s", VmEntry->kve_path);
796d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  }
806d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
816d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  current_ += VmEntry->kve_structsize;
826d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
836d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  return true;
846d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
856d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}  // namespace __sanitizer
876d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
886d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif  // SANITIZER_FREEBSD
89