sanitizer_linux.cc revision 6895adc39c4e09371154c8037366ad4464163ed0
1ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===-- sanitizer_linux.cc ------------------------------------------------===//
2ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
3ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//                     The LLVM Compiler Infrastructure
4ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
5ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is distributed under the University of Illinois Open Source
6ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// License. See LICENSE.TXT for details.
7ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
8ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===//
9ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
10ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer
11ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// run-time libraries and implements linux-specific functions from
12ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// sanitizer_libc.h.
13ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===//
14ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#ifdef __linux__
15ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common.h"
1794b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h"
18ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h"
196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h"
20ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
21c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h>
22ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h>
23c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h>
24ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h>
25ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h>
26ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h>
27ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
28ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer {
29ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
30ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovvoid *internal_mmap(void *addr, uptr length, int prot, int flags,
31ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov                    int fd, u64 offset) {
32ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#if __WORDSIZE == 64
33ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov  return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
34ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else
35ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov  return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
36ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif
37ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}
38ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
391f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovint internal_munmap(void *addr, uptr length) {
401f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov  return syscall(__NR_munmap, addr, length);
411f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
421f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
43a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovint internal_close(fd_t fd) {
44a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return syscall(__NR_close, fd);
45a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
46a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
47c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonovfd_t internal_open(const char *filename, bool write) {
48c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov  return syscall(__NR_open, filename,
499b8a9c1b1ce4659457178ff4c0838ac1b35ca9dcKostya Serebryany      write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
50c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov}
51c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
52a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) {
53a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return (uptr)syscall(__NR_read, fd, buf, count);
54a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
55a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
56a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) {
57a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return (uptr)syscall(__NR_write, fd, buf, count);
58a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
59a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
608e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) {
618e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  struct stat st = {};
628e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  if (syscall(__NR_fstat, fd, &st))
638e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov    return -1;
648e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return (uptr)st.st_size;
658e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
668e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
678e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovint internal_dup2(int oldfd, int newfd) {
688e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return syscall(__NR_dup2, oldfd, newfd);
698e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
708e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
716895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// ----------------- ProcessMaps implementation.
726895adc39c4e09371154c8037366ad4464163ed0Alexey SamsonovProcessMaps::ProcessMaps() {
736895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  proc_self_maps_buff_len_ =
746895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      ReadFileToBuffer("/proc/self/maps", &proc_self_maps_buff_,
756895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov                       &proc_self_maps_buff_mmaped_size_, 1 << 26);
766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  CHECK(proc_self_maps_buff_len_ > 0);
776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // internal_write(2, proc_self_maps_buff_, proc_self_maps_buff_len_);
786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  Reset();
796895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
806895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
816895adc39c4e09371154c8037366ad4464163ed0Alexey SamsonovProcessMaps::~ProcessMaps() {
826895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  UnmapOrDie(proc_self_maps_buff_, proc_self_maps_buff_mmaped_size_);
836895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
846895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
856895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonovvoid ProcessMaps::Reset() {
866895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_ = proc_self_maps_buff_;
876895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
886895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
896895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonovbool ProcessMaps::Next(uptr *start, uptr *end, uptr *offset,
906895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov                       char filename[], uptr filename_size) {
916895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  char *last = proc_self_maps_buff_ + proc_self_maps_buff_len_;
926895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (current_ >= last) return false;
936895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  int consumed = 0;
946895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  char flags[10];
956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  int major, minor;
966895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  uptr inode;
976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  uptr dummy;
986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!start) start = &dummy;
996895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!end) end = &dummy;
1006895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!offset) offset = &dummy;
1016895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
1026895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (next_line == 0)
1036895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    next_line = last;
1046895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (internal_sscanf(current_, "%lx-%lx %4s %lx %x:%x %ld %n",
1056895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov                      start, end, flags, offset, &major, &minor,
1066895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov                      &inode, &consumed) != 7)
1076895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    return false;
1086895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_ += consumed;
1096895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Skip spaces.
1106895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  while (current_ < next_line && *current_ == ' ')
1116895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    current_++;
1126895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Fill in the filename.
1136895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  uptr i = 0;
1146895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  while (current_ < next_line) {
1156895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (filename && i < filename_size - 1)
1166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      filename[i++] = *current_;
1176895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    current_++;
1186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  }
1196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (filename && i < filename_size)
1206895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    filename[i] = 0;
1216895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_ = next_line + 1;
1226895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return true;
1236895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
1246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
1256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Gets the object name and the offset by walking ProcessMaps.
1266895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonovbool ProcessMaps::GetObjectNameAndOffset(uptr addr, uptr *offset,
1276895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov                                         char filename[],
1286895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov                                         uptr filename_size) {
1296895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size);
1306895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
1316895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
132ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}  // namespace __sanitizer
133ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
134ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif  // __linux__
135