Skip to content

Commit e2e32c5

Browse files
committed
hw tracker
1 parent 7c5b20d commit e2e32c5

File tree

4 files changed

+67
-31
lines changed

4 files changed

+67
-31
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(AppleClang|Clang|GNU)$")
114114
add_flag(-Werror-non-virtual-dtor) # warn the user if a class with virtual functions has a non-virtual destructor. This helps catch hard to track down memory errors
115115
add_flag(-Werror-sign-compare) # warn the user if they compare a signed and unsigned numbers
116116
add_flag(-Werror-reorder) # field '$1' will be initialized after field '$2'
117+
118+
add_link_options(-rdynamic)
117119
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
118120
# using Visual Studio C++
119121
# TODO(warchant): add flags https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md#msvc

include/libp2p/muxer/yamux/hardware_tracker.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class HardwareSharedPtrTracker {
2323
}
2424

2525
// Start tracking the reference count of a shared_ptr
26-
void startTracking(std::shared_ptr<YamuxedConnection> ptr);
26+
void startTracking(const std::shared_ptr<YamuxedConnection>& ptr);
2727

2828
// Stop current tracking
2929
void stopTracking();
@@ -76,7 +76,7 @@ class HardwareSharedPtrTracker {
7676
};
7777

7878
// Global function for setting in yamux.cpp
79-
void trackNextYamuxedConnection(std::shared_ptr<YamuxedConnection> ptr);
79+
void trackNextYamuxedConnection(const std::shared_ptr<YamuxedConnection>& ptr);
8080

8181
// Macros for convenience
8282
#define YAMUX_HARDWARE_TRACK_ENABLE() \

src/muxer/yamux/hardware_tracker.cpp

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/perf_event.h>
77
#include <asm/unistd.h>
88
#include <cstdio>
9+
#include <fcntl.h>
910

1011
namespace libp2p::connection {
1112

@@ -45,11 +46,12 @@ void* HardwareSharedPtrTracker::getRefCountAddress(const std::shared_ptr<Yamuxed
4546
return nullptr;
4647
}
4748

48-
void* ref_count_addr = control_block;
49+
uint32_t* ref_count_addr = (uint32_t*)((uint8_t*)control_block + sizeof(void*));
4950

5051
std::cout << "Control block address: " << control_block << "\n";
5152
std::cout << "Reference count address: " << ref_count_addr << "\n";
5253
std::cout << "Current use_count: " << ptr.use_count() << "\n";
54+
assert(*ref_count_addr == ptr.use_count());
5355

5456
return ref_count_addr;
5557
}
@@ -61,22 +63,50 @@ bool HardwareSharedPtrTracker::setHardwareWatchpoint(void* address) {
6163
pe.type = PERF_TYPE_BREAKPOINT;
6264
pe.size = sizeof(pe);
6365
pe.config = 0;
64-
pe.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
66+
pe.bp_type = HW_BREAKPOINT_W; // Только запись, чтение может генерировать много событий
6567
pe.bp_addr = reinterpret_cast<uint64_t>(address);
66-
pe.bp_len = sizeof(long);
67-
pe.disabled = 0;
68+
pe.bp_len = HW_BREAKPOINT_LEN_4; // 4 байта для int
69+
pe.disabled = 0; // Включен сразу
6870
pe.exclude_kernel = 1;
6971
pe.exclude_hv = 1;
72+
pe.exclude_user = 0; // Отслеживаем user space
73+
pe.sample_period = 1; // Генерировать событие на каждое изменение
74+
pe.wakeup_events = 1; // Пробуждать на каждое событие
75+
76+
std::cout << "🔧 Настройка hardware watchpoint:\n";
77+
std::cout << " Адрес: " << address << "\n";
78+
std::cout << " bp_addr: 0x" << std::hex << pe.bp_addr << std::dec << "\n";
79+
std::cout << " bp_len: " << pe.bp_len << "\n";
80+
std::cout << " bp_type: " << pe.bp_type << " (только запись)\n";
7081

7182
int fd = syscall(__NR_perf_event_open, &pe, 0, -1, -1, 0);
7283
if (fd == -1) {
73-
perror("perf_event_open for hardware watchpoint failed");
84+
perror("❌ perf_event_open неудачен");
85+
std::cout << " Ошибка: " << strerror(errno) << "\n";
86+
std::cout << " Код ошибки: " << errno << "\n";
7487
return false;
7588
}
7689

90+
// Настраиваем доставку сигнала
91+
struct f_owner_ex owner;
92+
owner.type = F_OWNER_TID;
93+
owner.pid = syscall(SYS_gettid);
94+
95+
if (fcntl(fd, F_SETOWN_EX, &owner) == -1) {
96+
perror("⚠️ fcntl F_SETOWN_EX failed");
97+
}
98+
99+
if (fcntl(fd, F_SETFL, O_ASYNC) == -1) {
100+
perror("⚠️ fcntl F_SETFL failed");
101+
}
102+
103+
if (fcntl(fd, F_SETSIG, SIGTRAP) == -1) {
104+
perror("⚠️ fcntl F_SETSIG failed");
105+
}
106+
77107
watchpoint_fd_ = fd;
78108

79-
std::cout << "Hardware watchpoint set on address " << address
109+
std::cout << "Hardware watchpoint установлен на адрес " << address
80110
<< " (fd=" << fd << ")\n";
81111

82112
return true;
@@ -96,33 +126,43 @@ void HardwareSharedPtrTracker::signalHandler(int sig, siginfo_t* info, void* con
96126
if (!instance_ || sig != SIGTRAP) {
97127
return;
98128
}
99-
100-
// printStackTrace();
101129

102130
static int call_number = 0;
103131
call_number++;
104132

105-
const char msg[] = "\n=== HARDWARE BREAKPOINT: REFERENCE COUNT CHANGED ===\n";
133+
const char msg[] = "\n🚨 === HARDWARE BREAKPOINT: REFERENCE COUNT CHANGED === 🚨\n";
106134
write(STDOUT_FILENO, msg, sizeof(msg) - 1);
107135

108-
char call_msg[100];
109-
int len = snprintf(call_msg, sizeof(call_msg), "Call #%d - Address: %p\n", call_number, info->si_addr);
136+
char call_msg[200];
137+
int len = snprintf(call_msg, sizeof(call_msg), "📍 Изменение #%d - Адрес: %p\n", call_number, info->si_addr);
110138
write(STDOUT_FILENO, call_msg, len);
111139

112-
const int max_frames = 15;
113-
void* buffer[max_frames];
114-
115-
const char stack_msg[] = "Stack trace (exact location of reference count change):\n";
140+
const char stack_msg[] = "📚 Стек трассировки (точное место изменения счетчика ссылок):\n";
116141
write(STDOUT_FILENO, stack_msg, sizeof(stack_msg) - 1);
117142

143+
// Получаем стек трассировки
144+
const int max_frames = 7;
145+
void* buffer[max_frames];
118146
int nframes = backtrace(buffer, max_frames);
119147

120-
backtrace_symbols_fd(buffer, nframes, STDOUT_FILENO);
148+
// Используем backtrace_symbols для получения символов
149+
char** symbols = backtrace_symbols(buffer, nframes);
121150

122-
const char end_msg[] = "================================================\n\n";
123-
write(STDOUT_FILENO, end_msg, sizeof(end_msg) - 1);
151+
if (symbols) {
152+
for (int i = 0; i < nframes; ++i) {
153+
char frame_msg[500];
154+
int frame_len = snprintf(frame_msg, sizeof(frame_msg),
155+
" [%2d] %s\n", i, symbols[i]);
156+
write(STDOUT_FILENO, frame_msg, frame_len);
157+
}
158+
free(symbols);
159+
} else {
160+
// Fallback - используем backtrace_symbols_fd если symbols == NULL
161+
backtrace_symbols_fd(buffer, nframes, STDOUT_FILENO);
162+
}
124163

125-
//instance_->signal_count_.fetch_add(1, std::memory_order_relaxed);
164+
const char end_msg[] = "🔚 ============================================== 🔚\n\n";
165+
write(STDOUT_FILENO, end_msg, sizeof(end_msg) - 1);
126166
}
127167

128168
void HardwareSharedPtrTracker::printStackTrace() {
@@ -167,7 +207,7 @@ void HardwareSharedPtrTracker::checkAndSwitchIfNeeded() {
167207
}
168208
}
169209

170-
void HardwareSharedPtrTracker::startTracking(std::shared_ptr<YamuxedConnection> ptr) {
210+
void HardwareSharedPtrTracker::startTracking(const std::shared_ptr<YamuxedConnection>& ptr) {
171211
if (!enabled_) {
172212
return;
173213
}
@@ -221,9 +261,9 @@ void HardwareSharedPtrTracker::stopTracking() {
221261
std::cout << "=================================\n\n";
222262
}
223263

224-
void trackNextYamuxedConnection(std::shared_ptr<YamuxedConnection> ptr) {
264+
void trackNextYamuxedConnection(const std::shared_ptr<YamuxedConnection>& ptr) {
225265
auto& tracker = HardwareSharedPtrTracker::getInstance();
226-
tracker.startTracking(std::move(ptr));
227-
}
266+
tracker.startTracking(ptr);
267+
}
228268

229269
} // namespace libp2p::connection

src/muxer/yamux/yamux.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@
88

99
#include <libp2p/log/logger.hpp>
1010
#include <libp2p/muxer/yamux/yamuxed_connection.hpp>
11-
12-
#ifdef YAMUX_HARDWARE_TRACKING
1311
#include <libp2p/muxer/yamux/hardware_tracker.hpp>
14-
#endif
1512

1613
namespace libp2p::muxer {
1714
Yamux::Yamux(MuxedConnectionConfig config,
@@ -50,10 +47,7 @@ namespace libp2p::muxer {
5047

5148
auto yamux_connection = std::make_shared<connection::YamuxedConnection>(
5249
std::move(conn), scheduler_, close_cb_, config_);
53-
54-
#ifdef YAMUX_HARDWARE_TRACKING
5550
connection::trackNextYamuxedConnection(yamux_connection);
56-
#endif
5751

5852
cb(yamux_connection);
5953
}

0 commit comments

Comments
 (0)