this repo has no description
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