Skip to content

Commit 684d45f

Browse files
Misc fixes so things build
1 parent aee99e2 commit 684d45f

File tree

9 files changed

+110
-97
lines changed

9 files changed

+110
-97
lines changed

libcxx/include/__stacktrace/images.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,13 @@ struct image;
2020
struct images;
2121

2222
struct image {
23-
constexpr static size_t __max_string_len = 1024;
24-
2523
uintptr_t loaded_at_{};
2624
uintptr_t slide_{};
27-
fixed_str<__max_string_len> name_{};
25+
fixed_str<PATH_MAX> name_{};
2826
bool is_main_prog_{};
2927

3028
bool operator<(image const& __rhs) const { return loaded_at_ < __rhs.loaded_at_; }
31-
operator bool() const { return name_[0]; }
29+
operator bool() const { return !name_.empty(); }
3230
};
3331

3432
/**

libcxx/include/__stacktrace/memory.h

Lines changed: 84 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -38,60 +38,59 @@ A few memory-related utilities:
3838
Uses the caller's provided allocator, so none of these involve heap allocations
3939
"outside of" the caller-provided allocator.
4040
* A `str` class, inheriting from `std::string`, ensuring allocations happen via `arena`
41-
* A `fixed_str` class, not related to the arena, but instead backed by a `char[n]`
42-
array within that same struct, so it doesn't perform any [de]allocations; it only
43-
uses its own character array.
4441
4542
A small amount of glue / hacks are done here to allow the rest of the stacktrace-related
4643
code to use familiar string etc. operations, while encapsulating away the details of where
4744
memory might come from, since we need to be careful about unexpected allocations.
4845
*/
4946

50-
// clang-format off
51-
5247
struct byte_pool final {
5348
byte* ptr_;
5449
function<void()> destroy_;
5550
byte_pool* link_;
5651
byte* end_;
5752

58-
byte_pool(byte* __bytes,
59-
size_t __size,
60-
function<void()> __destroy = [] {},
61-
byte_pool* __link = nullptr) noexcept
62-
: ptr_(__bytes), destroy_(__destroy), link_(__link), end_(__bytes + __size) {}
53+
byte_pool(
54+
byte* __bytes, size_t __size, function<void()> __destroy = [] {}, byte_pool* __link = nullptr) noexcept
55+
: ptr_(__bytes), destroy_(__destroy), link_(__link), end_(__bytes + __size) {}
6356

6457
byte* operator()(size_t __sz, size_t __align) noexcept {
65-
auto __ptr = uintptr_t(ptr_); // convert curr ptr to integer, to do math
66-
auto __misalign = __ptr % __align; // if current ptr not aligned,
67-
if (__misalign) { __ptr += (__align - __misalign); } // waste a few bytes to ensure alignment
68-
auto __ret = __ptr; // we would return this aligned position
69-
__ptr += __sz; // next object will start here
70-
if (__ptr > uintptr_t(end_)) { return nullptr; } // if this exceeds our space, then fail
71-
ptr_ = (byte*) __ptr; // otherwise update current position
72-
return (byte*) __ret; // returned aligned position as byte ptr
58+
auto __ptr = uintptr_t(ptr_); // convert curr ptr to integer, to do math
59+
auto __misalign = __ptr % __align; // if current ptr not aligned,
60+
if (__misalign) {
61+
__ptr += (__align - __misalign);
62+
} // waste a few bytes to ensure alignment
63+
auto __ret = __ptr; // we would return this aligned position
64+
__ptr += __sz; // next object will start here
65+
if (__ptr > uintptr_t(end_)) {
66+
return nullptr;
67+
} // if this exceeds our space, then fail
68+
ptr_ = (byte*)__ptr; // otherwise update current position
69+
return (byte*)__ret; // returned aligned position as byte ptr
7370
}
7471
};
7572

7673
template <size_t _Sz>
7774
struct stack_bytes final {
7875
byte bytes_[_Sz];
7976

80-
~stack_bytes() = default;
81-
stack_bytes() noexcept = default;
77+
~stack_bytes() = default;
78+
stack_bytes() noexcept = default;
8279
stack_bytes(const stack_bytes&) = delete;
83-
stack_bytes(stack_bytes&&) = delete;
80+
stack_bytes(stack_bytes&&) = delete;
8481

85-
byte_pool pool() { return {bytes_, _Sz, []{}, nullptr}; }
82+
byte_pool pool() {
83+
return {bytes_, _Sz, [] {}, nullptr};
84+
}
8685
};
8786

8887
struct arena {
89-
function<byte*(size_t)> new_bytes_; // new byte-array factory
90-
function<void(void*, size_t)> del_bytes_; // byte-array destroyer
91-
byte_pool* curr_pool_; // byte pool currently "in effect"
92-
byte_pool* next_pool_; // allocated (from curr_pool_) but not initialized
93-
size_t allocs_ {}; // number of successful allocations
94-
size_t deallocs_ {}; // incremented on each dealloc; dtor ensures these are equal!
88+
function<byte*(size_t)> new_bytes_; // new byte-array factory
89+
function<void(void*, size_t)> del_bytes_; // byte-array destroyer
90+
byte_pool* curr_pool_; // byte pool currently "in effect"
91+
byte_pool* next_pool_; // allocated (from curr_pool_) but not initialized
92+
size_t allocs_{}; // number of successful allocations
93+
size_t deallocs_{}; // incremented on each dealloc; dtor ensures these are equal!
9594

9695
// An arena is scoped to a `basic_stacktrace::current` invocation, so this is usable by only one thread.
9796
// Additionally, it's used internally throughout many function calls, so for convenience, store it here.
@@ -108,11 +107,14 @@ struct arena {
108107
_LIBCPP_ASSERT(active_arena_ptr_ == this, "different arena unexpectively set as the active one");
109108
active_arena_ptr_ = nullptr;
110109
_LIBCPP_ASSERT(deallocs_ == allocs_, "destructed arena still has live objects");
111-
while (curr_pool_) { curr_pool_->destroy_(); curr_pool_ = curr_pool_->link_; }
110+
while (curr_pool_) {
111+
curr_pool_->destroy_();
112+
curr_pool_ = curr_pool_->link_;
113+
}
112114
}
113115

114116
arena(auto&& __new_bytes, auto&& __del_bytes, byte_pool& __initial_pool) noexcept
115-
: new_bytes_(__new_bytes), del_bytes_(__del_bytes), curr_pool_(&__initial_pool) {
117+
: new_bytes_(__new_bytes), del_bytes_(__del_bytes), curr_pool_(&__initial_pool) {
116118
prep_next_pool();
117119
_LIBCPP_ASSERT(!active_arena_ptr_, "already an active arena");
118120
active_arena_ptr_ = this;
@@ -125,24 +127,25 @@ struct arena {
125127

126128
template <class _UA>
127129
arena(byte_pool& __initial_pool, _UA const& __user_alloc)
128-
: arena(
129-
[&__user_alloc] (size_t __sz) { return as_byte_alloc(__user_alloc).allocate(__sz); },
130-
[&__user_alloc] (void* __ptr, size_t __sz) { return as_byte_alloc(__user_alloc).deallocate((byte*)__ptr, __sz); },
131-
__initial_pool) {}
130+
: arena([&__user_alloc](size_t __sz) { return as_byte_alloc(__user_alloc).allocate(__sz); },
131+
[&__user_alloc](void* __ptr, size_t __sz) {
132+
return as_byte_alloc(__user_alloc).deallocate((byte*)__ptr, __sz);
133+
},
134+
__initial_pool) {}
132135

133136
arena(arena const&) = delete;
134137
arena& operator=(arena const&) = delete;
135138

136139
void prep_next_pool() noexcept {
137140
// Allocate (via current pool) a new byte_pool record, while we have enough space.
138141
// When the current pool runs out of space, this one will be ready to use.
139-
next_pool_ = (byte_pool*) (*curr_pool_)(sizeof(byte_pool), alignof(byte_pool));
142+
next_pool_ = (byte_pool*)(*curr_pool_)(sizeof(byte_pool), alignof(byte_pool));
140143
_LIBCPP_ASSERT(next_pool_, "could not allocate next pool");
141144
}
142145

143146
void expand(size_t __atleast) noexcept {
144147
constexpr static size_t __k_default_new_pool = 1 << 12;
145-
auto __size = max(__atleast, __k_default_new_pool);
148+
auto __size = max(__atleast, __k_default_new_pool);
146149
// "next_pool_" was already allocated, just need to initialize it
147150
auto* __bytes = new_bytes_(__size);
148151
_LIBCPP_ASSERT(__bytes, "could not allocate more bytes for arena");
@@ -155,12 +158,14 @@ struct arena {
155158

156159
std::byte* alloc(size_t __size, size_t __align) noexcept {
157160
auto* __ret = (*curr_pool_)(__size, __align);
158-
if (__ret) [[likely]] { goto success; }
161+
if (__ret) [[likely]] {
162+
goto success;
163+
}
159164
// Need a new pool to accommodate this request + internal structs
160165
expand(__size + __align + sizeof(byte_pool) + alignof(byte_pool)); // upper bound
161166
__ret = (*curr_pool_)(__size, __align);
162167
_LIBCPP_ASSERT(__ret, "arena failed to allocate");
163-
success:
168+
success:
164169
++allocs_;
165170
return __ret;
166171
}
@@ -181,31 +186,6 @@ struct alloc {
181186
}
182187
};
183188

184-
template <typename _Tp, size_t _Sz>
185-
struct fixed_buf {
186-
using value_type = _Tp;
187-
template <typename _Up> struct rebind { using other = fixed_buf<_Up, _Sz>; };
188-
189-
_Tp __buf_[_Sz];
190-
size_t __size_;
191-
void deallocate(_Tp*, size_t) {}
192-
_Tp* allocate(size_t) { return __buf_; }
193-
};
194-
195-
template <size_t _Sz>
196-
struct fixed_str : std::basic_string<char, std::char_traits<char>, fixed_buf<char, _Sz>> {
197-
using _Base _LIBCPP_NODEBUG = std::basic_string<char, std::char_traits<char>, fixed_buf<char, _Sz>>;
198-
using _Base::operator=;
199-
200-
fixed_buf<char, _Sz> __fb_;
201-
fixed_str() : _Base(__fb_) {
202-
this->resize(_Sz - 1);
203-
this->resize(0);
204-
}
205-
fixed_str(fixed_str const& __rhs) : fixed_str() { _Base::operator=(__rhs); }
206-
fixed_str& operator=(fixed_str const& __rhs) = default;
207-
};
208-
209189
struct str : std::basic_string<char, std::char_traits<char>, alloc<char>> {
210190
using _Base _LIBCPP_NODEBUG = std::basic_string<char, std::char_traits<char>, alloc<char>>;
211191
using _Base::basic_string;
@@ -236,7 +216,47 @@ struct str : std::basic_string<char, std::char_traits<char>, alloc<char>> {
236216
}
237217
};
238218

239-
// clang-format on
219+
/** A string that contains its own fixed-size, fixed-location buffer. */
220+
template <size_t _Sz>
221+
struct fixed_str final {
222+
size_t __size_{0};
223+
char __buf_[_Sz]{0};
224+
225+
~fixed_str() = default;
226+
fixed_str() = default;
227+
228+
size_t size() const { return __size_; }
229+
bool empty() const { return !size(); }
230+
auto* data(this auto& __self) { return __self.__buf_; }
231+
operator std::string_view() const { return {__buf_, __size_}; }
232+
233+
fixed_str& operator=(std::string_view __sv) {
234+
strncpy(__buf_, __sv.data(), std::min(_Sz, __sv.size() + 1));
235+
__size_ = __sv.size();
236+
__buf_[__size_] = 0;
237+
return *this;
238+
}
239+
240+
fixed_str(auto const& __rhs) : fixed_str() { *this = __rhs; }
241+
fixed_str& operator=(auto const& __rhs) { return (*this = std::string_view(__rhs)); }
242+
243+
template <size_t _S2>
244+
requires requires { _S2 <= _Sz; }
245+
fixed_str& operator=(fixed_str<_S2> const& __rhs) {
246+
return (*this = std::string_view(__rhs));
247+
}
248+
249+
template <size_t _S2>
250+
requires requires { _S2 <= _Sz; }
251+
fixed_str(fixed_str<_S2> const& __rhs) {
252+
*this = std::string_view(__rhs);
253+
}
254+
255+
fixed_str(fixed_str const& __rhs) { *this = std::string_view(__rhs); }
256+
fixed_str& operator=(fixed_str const& __rhs) { return (*this = std::string_view(__rhs)); }
257+
258+
friend std::ostream& operator<<(std::ostream& __os, fixed_str const& __f) { return __os << std::string_view(__f); }
259+
};
240260

241261
} // namespace __stacktrace
242262
_LIBCPP_END_NAMESPACE_STD

libcxx/src/stacktrace/images.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//
1212

1313
#include "__config"
14+
1415
#if defined(__APPLE__)
1516
// MacOS-specific: use the `dyld` loader to access info about loaded Mach-O images.
1617
# include <__stacktrace/images.h>

libcxx/src/stacktrace/impl_generic.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,10 @@ _LIBCPP_EXPORTED_FROM_ABI void base::find_symbols(arena& arena) {}
101101

102102
_LIBCPP_EXPORTED_FROM_ABI void base::find_source_locs(arena& arena) {
103103
# if __has_include(<spawn.h>) && _LIBCPP_STACKTRACE_ALLOW_TOOLS_AT_RUNTIME
104-
(void)(false //
105-
|| __run_tool<atos>(*this, arena) // preferred on MacOS
106-
|| __run_tool<llvm_symbolizer>(*this, arena) // prefer this in other (non-MacOS, non-Windows)
107-
|| __run_tool<addr2line>(*this, arena) // a good fallback; dev machines tend to have gcc if not llvm
108-
);
104+
(void)(false //
105+
|| (__has_working_executable<atos>() && __run_tool<atos>(*this, arena)) //
106+
|| (__has_working_executable<llvm_symbolizer>() && __run_tool<llvm_symbolizer>(*this, arena)) //
107+
|| (__has_working_executable<addr2line>() && __run_tool<addr2line>(*this, arena))); //
109108
# endif
110109
}
111110

libcxx/src/stacktrace/tools/apple_atos.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ template<> bool _LIBCPP_EXPORTED_FROM_ABI __run_tool<atos>(base& base, arena& ar
7171
spawner spawner{tool, base};
7272
if (spawner.errno_) { return false; }
7373

74-
fixed_str<PATH_MAX * 2> line; // our read buffer
74+
str line; // our read buffer
7575
auto* entry_iter = base.entries_begin(); // position at first entry
7676
while (spawner.stream_.good()) { // loop until we get EOF from tool stdout
7777
std::getline(spawner.stream_, line); // consume a line from stdout

libcxx/src/stacktrace/tools/gnu_addr2line.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ template<> bool _LIBCPP_EXPORTED_FROM_ABI __run_tool<addr2line>(base& base, aren
106106
spawner spawner{tool, base};
107107
if (spawner.errno_) { return false; }
108108

109-
fixed_str<PATH_MAX * 2> line; // our read buffer
109+
str line ; // our read buffer
110110
auto* entry_iter = base.entries_begin(); // position at first entry
111111
while (spawner.stream_.good()) { // loop until we get EOF from tool stdout
112112
std::string_view view;

libcxx/src/stacktrace/tools/llvm_symbolizer.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ bool llvm_symbolizer::build_argv() {
3838
while (it != end) {
3939
auto& entry = *(entry_base*)(it++);
4040
if (entry.__image_ && !entry.__image_->name_.empty()) {
41-
fixed_str<PATH_MAX> image_path = entry.__image_->name_;
42-
push_arg("FILE:%s %p", image_path.data(), (void*)entry.adjusted_addr());
41+
push_arg("FILE:%s %p", entry.__image_->name_.data(), (void*)entry.adjusted_addr());
4342
} else {
4443
push_arg("%p", (void*)entry.adjusted_addr());
4544
}
@@ -89,7 +88,7 @@ template<> bool _LIBCPP_EXPORTED_FROM_ABI __run_tool<llvm_symbolizer>(base& base
8988
spawner spawner{tool, base};
9089
if (spawner.errno_) { return false; }
9190

92-
fixed_str<PATH_MAX * 2> line; // our read buffer
91+
str line; // our read buffer
9392
auto* entry_iter = base.entries_begin() - 1; // "before first" entry
9493
while (spawner.stream_.good()) { // loop until we get EOF from tool stdout
9594
std::getline(spawner.stream_, line); // consume a line from stdout

libcxx/src/stacktrace/tools/tools.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ struct file_actions {
117117
optional<posix_spawn_file_actions_t> fa_{};
118118
fd stdout_read_; // read end of subprocess's stdout, IFF redir_stdout used
119119
fd stdout_write_; // write end of subprocess's stdout, IFF redir_stdout used
120-
errno_t errno_{}; // set to nonzero if any of these C calls failed
120+
int errno_{}; // set to nonzero if any of these C calls failed
121121

122122
bool failed() const { return errno_; }
123123

@@ -223,8 +223,8 @@ struct sigchld_enable {
223223

224224
struct pid_waiter {
225225
pid_t pid_{};
226-
int status_{}; // value is valid iff wait() completed
227-
errno_t errno_{}; // set to nonzero if any of these C calls failed
226+
int status_{}; // value is valid iff wait() completed
227+
int errno_{}; // set to nonzero if any of these C calls failed
228228
bool done_{};
229229

230230
operator pid_t() const { return pid_; }
@@ -271,7 +271,7 @@ struct spawner {
271271
fd::istream stream_; // istream interface from which we can `getline`
272272
sigchld_enable chld_enable_; // temporarily enables SIGCHLD so `waitpid` works
273273
pid_waiter pid_{0}; // set during successful `spawn`, can `waitpid` automatically
274-
errno_t errno_{}; // set to nonzero if any of these C calls failed
274+
int errno_{}; // set to nonzero if any of these C calls failed
275275

276276
bool failed() const { return errno_; }
277277

@@ -346,7 +346,7 @@ template <>
346346
bool _LIBCPP_EXPORTED_FROM_ABI __run_tool<atos>(base&, arena&);
347347

348348
struct llvm_symbolizer : tool_base {
349-
constexpr static char const* __default_prog_name = "llvm_symbolizer";
349+
constexpr static char const* __default_prog_name = "llvm-symbolizer";
350350
constexpr static char const* __override_prog_env = "LIBCXX_STACKTRACE_FORCE_LLVM_SYMBOLIZER_PATH";
351351

352352
llvm_symbolizer(base& base, arena& arena) : tool_base{base, arena, __executable_name<llvm_symbolizer>::get()} {}

0 commit comments

Comments
 (0)