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