| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 4a54f30 commit ca23511
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,10 +13,12 @@ | |||
| 13 | 13 | #include <sys/time.h> | |
| 14 | 14 | #include <sys/types.h> | |
| 15 | 15 | #include <sys/ucontext.h> | |
| 16 | + #include <sys/user.h> | ||
| 16 | 17 | ||
| 17 | 18 | #include <sys/fcntl.h> // open | |
| 18 | 19 | #include <sys/mman.h> // mmap & munmap | |
| 19 | 20 | #include <sys/stat.h> // open | |
| 21 | + #include <sys/sysctl.h> | ||
| 20 | 22 | #include <unistd.h> // getpagesize | |
| 21 | 23 | // If you don't have execinfo.h then you need devel/libexecinfo from ports. | |
| 22 | 24 | #include <errno.h> | |
@@ -46,41 +48,47 @@ static unsigned StringToLong(char* buffer) { | |||
| 46 | 48 | ||
| 47 | 49 | std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { | |
| 48 | 50 | std::vector<SharedLibraryAddress> result; | |
| 49 | - static const int MAP_LENGTH = 1024; | ||
| 50 | - int fd = open("/proc/self/maps", O_RDONLY); | ||
| 51 | - if (fd < 0) return result; | ||
| 52 | - while (true) { | ||
| 53 | - char addr_buffer[11]; | ||
| 54 | - addr_buffer[0] = '0'; | ||
| 55 | - addr_buffer[1] = 'x'; | ||
| 56 | - addr_buffer[10] = 0; | ||
| 57 | - ssize_t bytes_read = read(fd, addr_buffer + 2, 8); | ||
| 58 | - if (bytes_read < 8) break; | ||
| 59 | - unsigned start = StringToLong(addr_buffer); | ||
| 60 | - bytes_read = read(fd, addr_buffer + 2, 1); | ||
| 61 | - if (bytes_read < 1) break; | ||
| 62 | - if (addr_buffer[2] != '-') break; | ||
| 63 | - bytes_read = read(fd, addr_buffer + 2, 8); | ||
| 64 | - if (bytes_read < 8) break; | ||
| 65 | - unsigned end = StringToLong(addr_buffer); | ||
| 66 | - char buffer[MAP_LENGTH]; | ||
| 67 | - bytes_read = -1; | ||
| 68 | - do { | ||
| 69 | - bytes_read++; | ||
| 70 | - if (bytes_read >= MAP_LENGTH - 1) break; | ||
| 71 | - bytes_read = read(fd, buffer + bytes_read, 1); | ||
| 72 | - if (bytes_read < 1) break; | ||
| 73 | - } while (buffer[bytes_read] != '\n'); | ||
| 74 | - buffer[bytes_read] = 0; | ||
| 75 | - // Ignore mappings that are not executable. | ||
| 76 | - if (buffer[3] != 'x') continue; | ||
| 77 | - char* start_of_path = index(buffer, '/'); | ||
| 78 | - // There may be no filename in this line. Skip to next. | ||
| 79 | - if (start_of_path == nullptr) continue; | ||
| 80 | - buffer[bytes_read] = 0; | ||
| 81 | - result.push_back(SharedLibraryAddress(start_of_path, start, end)); | ||
| 51 | + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; | ||
| 52 | + size_t miblen = sizeof(mib) / sizeof(mib[0]); | ||
| 53 | + size_t buffer_size; | ||
| 54 | + if (sysctl(mib, miblen, nullptr, &buffer_size, nullptr, 0) == 0) { | ||
| 55 | + // Overallocate the buffer by 1/3 to account for concurrent | ||
| 56 | + // kinfo_vmentry change. 1/3 is an arbitrary constant that | ||
| 57 | + // works in practice. | ||
| 58 | + buffer_size = buffer_size * 4 / 3; | ||
| 59 | + std::vector<char> buffer(buffer_size); | ||
| 60 | + int ret = sysctl(mib, miblen, buffer.data(), &buffer_size, nullptr, 0); | ||
| 61 | + | ||
| 62 | + if (ret == 0 || (ret == -1 && errno == ENOMEM)) { | ||
| 63 | + char* start = buffer.data(); | ||
| 64 | + char* end = start + buffer_size; | ||
| 65 | + | ||
| 66 | + while (start < end) { | ||
| 67 | + struct kinfo_vmentry* map = | ||
| 68 | + reinterpret_cast<struct kinfo_vmentry*>(start); | ||
| 69 | + const size_t ssize = map->kve_structsize; | ||
| 70 | + char* path = map->kve_path; | ||
| 71 | + | ||
| 72 | + CHECK_NE(0, ssize); | ||
| 73 | + | ||
| 74 | + if ((map->kve_protection & KVME_PROT_READ) != 0 && | ||
| 75 | + (map->kve_protection & KVME_PROT_EXEC) != 0 && path[0] != '\0') { | ||
| 76 | + char* sep = strrchr(path, '/'); | ||
| 77 | + std::string lib_name; | ||
| 78 | + if (sep != nullptr) { | ||
| 79 | + lib_name = std::string(++sep); | ||
| 80 | + } else { | ||
| 81 | + lib_name = std::string(path); | ||
| 82 | + } | ||
| 83 | + result.push_back(SharedLibraryAddress( | ||
| 84 | + lib_name, reinterpret_cast<uintptr_t>(map->kve_start), | ||
| 85 | + reinterpret_cast<uintptr_t>(map->kve_end))); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + start += ssize; | ||
| 89 | + } | ||
| 90 | + } | ||
| 82 | 91 | } | |
| 83 | - close(fd); | ||
| 84 | 92 | return result; | |
| 85 | 93 | } | |
| 86 | 94 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments