Странная программа C ++ разбила с %RIP = 0x8C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Странная программа C ++ разбила с %RIP = 0x8

Сообщение Anonymous »

У меня есть многопоточная программа C ++, используя пользовательский класс шаблона без блокировки. Время от времени (раз в несколько месяцев в рамках тысяч процессов) программа сбивается в методе POP (). Coredump показывает %RIP = 0x8 , в то время как другие регистры кажутся нормальными. Сбой всегда происходит в одной и той же инструкции JMP 0x112d3c2 .
Другими словами, мой код Exeucte JMP 0x112d3c2 , и в этот момент %RIP внезапно поврежден. Каждый сбой происходит точно так же. Когда Callee выполняет retq , неправильный адрес загружается в %rip .

Ни один из них не подходит:

Код никогда не использует указатели функций или виртуальные функции, и разучная приема не показывает соблюдательный вызов или JMP.%rsp IS 0x0000000001247344 , который именно является обратным адресом вызывающего абонента и не был поврежден. /> Ядро составляет 4.18.0-147 , а ЦП-это intel (r) xeon (r) platinum 8352y
ниже мой подробный процесс анализа:
PrettyPrint-Override ">0x000000000112d320 : cmpb $0x0,(%rdi) // if (!inited_)
0x000000000112d323 : je 0x112d390
0x000000000112d325 : mov 0x10(%rdi),%r8 // r8 = size_
0x000000000112d329 : mov 0x18(%rdi),%rcx // rcx(oldv) = consumer_
0x000000000112d32d : lea 0x18(%rdi),%r9 // r9 = &consumer_
0x000000000112d331 : nopl 0x0(%rax)
0x000000000112d338 : mov 0x20(%rdi),%rax // rax = producer_
0x000000000112d33c : cmp %rcx,%rax // while (oldv < producer_)
0x000000000112d33f : jbe 0x112d36c
0x000000000112d341 : mov %rcx,%rax // rax = consumer_
0x000000000112d344 : xor %edx,%edx
0x000000000112d346 : div %r8 // rdx = consumer_ % size_; rax = consumer_ / size_
0x000000000112d349 : mov 0x8(%rdi),%rax // rax = data_
0x000000000112d34d : mov (%rax,%rdx,8),%rax // rax = data_ + index
0x000000000112d351 : lea 0x0(,%rdx,8),%rsi // rsi = index * 8
0x000000000112d359 : test %rax,%rax // nullptr == *(&(data_[index].v))
0x000000000112d35c : jne 0x112d370
0x000000000112d35e : pause // equal branch:
0x000000000112d360 : mov (%r9),%rcx // oldv = consumer_
0x000000000112d363 : mov 0x20(%rdi),%rax // rax = producer_
0x000000000112d367 : cmp %rcx,%rax // while (oldv < producer_)
0x000000000112d36a : ja 0x112d341
0x000000000112d36c : xor %eax,%eax
0x000000000112d36e : retq
0x000000000112d36f : nop
0x000000000112d370 : lea 0x1(%rcx),%rdx // not equal branch:
// rdx = oldv + 1
0x000000000112d374 : mov %rcx,%rax // rax = oldv
0x000000000112d377 : lock cmpxchg %rdx,(%r9) // if (*r9 == rax) { *r9 = rdx } else { rax = r9 }
// i.e., if (consumer_ == cmpv) { consumer_ = oldv + 1 } else { oldv = consumer_ }
0x000000000112d37c : cmp %rax,%rcx // if (oldv != cmpv)
0x000000000112d37f : je 0x112d3b8
0x000000000112d381 : mov %rax,%rcx // equal branch:
// cmpv = oldv
0x000000000112d384 : jmp 0x112d338
0x000000000112d386 : nopw %cs:0x0(%rax,%rax,1)
0x000000000112d390 : push %rbp // get logger, jump from
0x000000000112d391 : mov %rsp,%rbp // get logger
0x000000000112d394 : push %r12 // get logger
0x000000000112d396 : mov %rdi,%r12 // get logger
0x000000000112d399 : push %rbx // get logger
0x000000000112d39a : callq 0xfc7850 // get logger
0x000000000112d39f : cmpq $0x4,0xfe8(%rax)
0x000000000112d3a7 : jle 0x112d3d8
0x000000000112d3a9 : xor %eax,%eax
0x000000000112d3ab : lea -0x10(%rbp),%rsp
0x000000000112d3af : pop %rbx
0x000000000112d3b0 : pop %r12
0x000000000112d3b2 : pop %rbp
0x000000000112d3b3 : retq
0x000000000112d3b4 : nopl 0x0(%rax)
0x000000000112d3b8 : xor %ecx,%ecx // jump from , not equal branch
// %rcx = 0
0x000000000112d3ba : jmp 0x112d3c2
0x000000000112d3bc : nopl 0x0(%rax)
0x000000000112d3c0 : pause
0x000000000112d3c2 : mov 0x8(%rdi),%rdx // rdx = data_
0x000000000112d3c6 : mov %rcx,%rax // rax = 0x0
0x000000000112d3c9 : xchg %rax,(%rdx,%rsi,1) // ret(%rax) = data_[index].v; data_[index].v = nullptr
0x000000000112d3cd : test %rax,%rax // while (ret == nullptr)
0x000000000112d3d0 : je 0x112d3c0
// not equal branch:
0x000000000112d3d2 : retq // return ret;
0x000000000112d3d3 : nopl 0x0(%rax,%rax,1)
0x000000000112d3d8 : callq 0xfc9670 // get log buffer
0x000000000112d3dd : mov %rax,%rbx
0x000000000112d3e0 : test %rax,%rax
0x000000000112d3e3 : je 0x112d3a9
0x000000000112d3e5 : lea 0x1a28b15(%rip),%rax # 0x2b55f01
0x000000000112d3ec : push %r12
0x000000000112d3ee : mov %rbx,%rdi
0x000000000112d3f1 : lea 0x1721950(%rip),%r9 # 0x284ed48
0x000000000112d3f8 : push %rax
0x000000000112d3f9 : lea 0x174b6f5(%rip),%r8 # 0x2878af5
0x000000000112d400 : mov $0x9d,%ecx
0x000000000112d405 : lea 0x1720fa2(%rip),%rsi # 0x284e3ae
0x000000000112d40c : lea 0x1725a85(%rip),%rdx # 0x2852e98
0x000000000112d413 : callq 0x112d170
0x000000000112d418 : pop %rax
0x000000000112d419 : pop %rdx
0x000000000112d41a : callq 0xfc7850
0x000000000112d41f : mov 0x1038(%rbx),%rdx
0x000000000112d426 : mov %rbx,%rsi
0x000000000112d429 : mov %rax,%rdi
0x000000000112d42c : callq 0xfc9040
0x000000000112d431 : xor %eax,%eax
0x000000000112d433 : jmpq 0x112d3ab
< /code>
Состояние очереди coredump: < /p>
queue: {inited_ = true, data_ = 0x7f028a24bb18, size_ = 100000, consumer_ = 11486375337, producer_ = 11486375759}
< /code>
Состояние регистрации coredump: < /p>
rax = 11486375336
rbx = 0x7f03137169d8
rcx = 0
rdx = 11486375337
rsi = 602688
rdi = 0x7f03137169e0
r8 = 100000
r9 = 0x7f03137169f8
rip = 0x8
rsp = 0x7f01e4567578
< /code>
Сравнение двух, это очевидно: < /p>
r8 = size_
r9 = &consumer_
rsi = index * 8
rdx = consumer_ + 1
rax = consumer_
rcx = 0x0


от Consumer_ = 11486375337 , %rcx = 0 мы знаем, что +87 блокировать cmpxchg %rdx, ( %r9) и +152 xor %ecx, %ecx имеет оба завершенные. & Data _ мы видим, что +162 MOV 0x8 (%RDI),%rdx имеет , пока не выполняется . /> < /ul>
Исходный код без блокировки < /p>
template
class LockfreeQueue {
struct Node {
T *volatile v;
};
public:
int Push(T *ptr);
T *Pop();
private:
bool inited_;
Node *data_;
int64_t size_;
volatile uint64_t consumer_;
volatile uint64_t producer_;
};

template
T *LockfreeQueue::Pop() {
T *ret = nullptr;

if (!inited_) {
LOG_WARN_KV("have not inited", KV("this", *this));
} else {
const uint64_t size = size_;
uint64_t oldv = consumer_;
uint64_t cmpv = oldv;
int64_t index = 0;
bool bret = false;

while (oldv < producer_) {
index = oldv % size;

if (nullptr == ({
asm volatile("" ::: "memory");
*(&(data_[index].v));
})) {
asm("pause\n");
oldv = ({
asm volatile("" ::: "memory");
*(&consumer_);
});
cmpv = oldv;
} else if (cmpv != (oldv = __sync_val_compare_and_swap((&consumer_), (cmpv), (oldv + 1)))) {
cmpv = oldv;
} else {
bret = true;
break;
}
}

if (bret) {
while (nullptr == (ret = (T *)__sync_lock_test_and_set((&(data_[index].v)), ((T *) nullptr)))) {
asm("pause\n");
}
}
}

return ret;
}

template
int LockfreeQueue::Push(T *ptr) {
int ret = ERR_SUCCESS;

if (!inited_) {
LOG_WARN_KV("have not inited", K(ptr), KV("this", *this));
ret = ERR_NOT_INITED;
} else if (nullptr == ptr) {
LOG_WARN_KV("invalid arg", K(ptr), KV("this", *this));
ret = ERR_INVALID_ARG;
} else {
const uint64_t size = size_;
uint64_t oldv = producer_;
uint64_t cmpv = oldv;
ret = ERR_QUEUE_FULL;

while (oldv < (consumer_ + size)) {
if (cmpv != (oldv = __sync_val_compare_and_swap((&producer_), (cmpv), (oldv + 1)))) {
cmpv = oldv;
} else {
ret = ERR_SUCCESS;
break;
}
}

if (ERR_SUCCESS == ret) {
int64_t index = oldv % size;
T *old = NULL;

while (old != __sync_val_compare_and_swap((&(data_[index].v)), (old), (ptr))) {
asm("pause\n");
}
}
}

return ret;
}
}


Подробнее здесь: https://stackoverflow.com/questions/797 ... th-rip-0x8
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»