Skip to content

Commit 08b8de1

Browse files
committed
Get from_current working in openbsd
1 parent b68da7d commit 08b8de1

File tree

3 files changed

+20
-1
lines changed

3 files changed

+20
-1
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,8 @@ jobs:
10171017
-DCMAKE_BUILD_TYPE=Debug \
10181018
-DCPPTRACE_WERROR_BUILD=On \
10191019
-DCPPTRACE_STD_FORMAT=Off \
1020-
-DCPPTRACE_BUILD_TESTING=On
1020+
-DCPPTRACE_BUILD_TESTING=On \
1021+
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-z,norelro"
10211022
ninja
10221023
./unittest
10231024

src/from_current.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,13 +294,28 @@ namespace detail {
294294
if(type_info_addr - page_addr + sizeof(void*) > static_cast<unsigned>(page_size)) {
295295
throw internal_error("pointer crosses page boundaries");
296296
}
297+
#if IS_WINDOWS
297298
auto old_protections = mprotect_page_and_return_old_protections(
298299
reinterpret_cast<void*>(page_addr),
299300
page_size,
300301
memory_readwrite
301302
);
302303
*static_cast<void**>(type_info_pointer) = static_cast<void*>(new_vtable + 2);
303304
mprotect_page(reinterpret_cast<void*>(page_addr), page_size, old_protections);
305+
#else
306+
auto old_protections = get_page_protections(reinterpret_cast<void*>(page_addr));
307+
// If the page is already writable, skip mprotect entirely.
308+
// This isn't just an optimization, it's needed on openbsd where mprotect would fail with EPERM but we can use
309+
// -Wl,-z,norelro to make the pages we care about writable
310+
bool need_mprotect = !(old_protections & PROT_WRITE);
311+
if(need_mprotect) {
312+
mprotect_page(reinterpret_cast<void*>(page_addr), page_size, memory_readwrite);
313+
}
314+
*static_cast<void**>(type_info_pointer) = static_cast<void*>(new_vtable + 2);
315+
if(need_mprotect) {
316+
mprotect_page(reinterpret_cast<void*>(page_addr), page_size, old_protections);
317+
}
318+
#endif
304319
}
305320

306321
bool can_catch(

src/platform/memory_mapping.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ namespace detail {
2121
constexpr auto memory_readwrite = PROT_READ | PROT_WRITE;
2222
#endif
2323
int get_page_size();
24+
#if !IS_WINDOWS
25+
int get_page_protections(void* page);
26+
#endif
2427
int mprotect_page_and_return_old_protections(void* page, int page_size, int protections);
2528
void mprotect_page(void* page, int page_size, int protections);
2629
void* allocate_page(int page_size);

0 commit comments

Comments
 (0)