this repo has no description
at trunk 132 lines 4.7 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "utils.h" 3 4#include <dlfcn.h> 5 6#include <cstring> 7#include <iostream> 8#include <sstream> 9#include <vector> 10 11#include "debugging.h" 12#include "file.h" 13#include "frame.h" 14#include "handles.h" 15#include "runtime.h" 16#include "thread.h" 17#include "traceback-builtins.h" 18 19namespace py { 20 21word Utils::memoryFind(const byte* haystack, word haystack_len, 22 const byte* needle, word needle_len) { 23 DCHECK(haystack != nullptr, "haystack cannot be null"); 24 DCHECK(needle != nullptr, "needle cannot be null"); 25 DCHECK(haystack_len >= 0, "haystack length must be nonnegative"); 26 DCHECK(needle_len >= 0, "needle length must be nonnegative"); 27 // We need something to compare 28 if (haystack_len == 0 || needle_len == 0) return -1; 29 // The needle is too big to be contained in haystack 30 if (haystack_len < needle_len) return -1; 31 const void* result; 32 if (needle_len == 1) { 33 // Fast path: one character 34 result = std::memchr(haystack, *needle, haystack_len); 35 } else { 36 result = ::memmem(haystack, haystack_len, needle, needle_len); 37 } 38 if (result == nullptr) return -1; 39 return static_cast<const byte*>(result) - haystack; 40} 41 42word Utils::memoryFindChar(const byte* haystack, word haystack_len, 43 byte needle) { 44 DCHECK(haystack != nullptr, "haystack cannot be null"); 45 DCHECK(haystack_len >= 0, "haystack length must be nonnegative"); 46 const void* result = std::memchr(haystack, needle, haystack_len); 47 if (result == nullptr) return -1; 48 return static_cast<const byte*>(result) - haystack; 49} 50 51word Utils::memoryFindCharReverse(const byte* haystack, word haystack_len, 52 byte needle) { 53 DCHECK(haystack != nullptr, "haystack cannot be null"); 54 DCHECK(haystack_len >= 0, "haystack length must be nonnegative"); 55 for (word i = haystack_len - 1; i >= 0; i--) { 56 if (haystack[i] == needle) return i; 57 } 58 return -1; 59} 60 61word Utils::memoryFindReverse(const byte* haystack, word haystack_len, 62 const byte* needle, word needle_len) { 63 DCHECK(haystack != nullptr, "haystack cannot be null"); 64 DCHECK(needle != nullptr, "needle cannot be null"); 65 DCHECK(haystack_len >= 0, "haystack length must be nonnegative"); 66 DCHECK(needle_len >= 0, "needle length must be nonnegative"); 67 // We need something to compare 68 if (haystack_len == 0 || needle_len == 0) return -1; 69 // The needle is too big to be contained in haystack 70 if (haystack_len < needle_len) return -1; 71 byte needle_start = *needle; 72 if (needle_len == 1) { 73 // Fast path: one character 74 return memoryFindCharReverse(haystack, haystack_len, needle_start); 75 } 76 // The last position where its possible to find needle in haystack 77 word last_offset = haystack_len - needle_len; 78 for (word i = last_offset; i >= 0; i--) { 79 if (haystack[i] == needle_start && 80 std::memcmp(haystack + i, needle, needle_len) == 0) { 81 return i; 82 } 83 } 84 return -1; 85} 86 87void Utils::printDebugInfoAndAbort() { 88 static thread_local bool aborting = false; 89 if (aborting) { 90 std::cerr << "Attempting to abort while already aborting. Not printing " 91 "another traceback.\n"; 92 std::abort(); 93 } 94 aborting = true; 95 96 Thread* thread = Thread::current(); 97 if (thread != nullptr) { 98 Runtime* runtime = thread->runtime(); 99 runtime->printTraceback(thread, File::kStderr); 100 if (thread->hasPendingException()) { 101 HandleScope scope(thread); 102 Object type(&scope, thread->pendingExceptionType()); 103 Object value(&scope, thread->pendingExceptionValue()); 104 Object traceback_obj(&scope, thread->pendingExceptionTraceback()); 105 thread->clearPendingException(); 106 107 std::cerr << "Pending exception\n Type : " << type 108 << "\n Value : " << value; 109 if (runtime->isInstanceOfBaseException(*value)) { 110 BaseException exception(&scope, *value); 111 std::cerr << "\n Exception Args: " << exception.args(); 112 } 113 std::cerr << "\n"; 114 if (traceback_obj.isTraceback()) { 115 Traceback traceback(&scope, *traceback_obj); 116 std::cerr << " Traceback : " << traceback << '\n'; 117 118 ValueCell stderr_cell(&scope, runtime->sysStderr()); 119 if (!stderr_cell.isUnbound()) { 120 Object stderr(&scope, stderr_cell.value()); 121 CHECK(!tracebackWrite(thread, traceback, stderr).isErrorException(), 122 "failed to print traceback"); 123 CHECK(!thread->invokeMethod1(stderr, ID(flush)).isErrorException(), 124 "failed to flush"); 125 } 126 } 127 } 128 } 129 std::abort(); 130} 131 132} // namespace py