2017-09-21 130 views
-1
obj.CurrSize -= size; 
0x00000000003ad2d7 <+183>: mov eax,0x0  
0x00000000003ad2dc <+188>: test rax,rax 
0x00000000003ad2df <+191>: je 0x3ad2e6 <+198> 
0x00000000003ad2e1 <+193>: call 0x0 
0x00000000003ad2e6 <+198>: mov rax, 0xffffffffffffff60 
0x00000000003ad2ed <+205>: sub rbx,r15 
0x00000000003ad2f0 <+208>: add QWORD PTR fs:[rax],rbx` 

爲什麼要測試零,然後如果爲零,跳過一條指令,但其他人也一樣?這個asm代碼是什麼意思?

+0

嘗試移除該位,看看它是否有所作爲。 –

+0

@MadPhysicist? – vladon

+0

@PeterCordes它與-O2一起叮噹響。看,有eax歸零,但rax測試。 – vladon

回答

2

讀一個無關的問題,exposes a pattern that looked similar to yours,我想我找到了你的奇怪代碼的由來。

最大的可能是這個代碼來自線程相關的C++ 11功能的擴展,在使用__gthread_active_p()檢查,如果pthread庫中居然掛特別的東西。

是有可能

大多數代碼應對線程的libstdC++的問題(但如果不需要線程支持合理的回退)充斥着

if(__gthread_active_p()) 

這又通常歸結爲檢查是否符號__pthread_key_create是定義爲不同於NULL的內容。這裏的訣竅是,這樣一個函數是,它被聲明爲__attribute__ ((weak)),所以,如果沒有提供定義(即如果pthread庫未鏈接),而不是抱怨,鏈接器只是解析其對NULL的引用。

所以,你在代碼中看到的是編譯器留下來做線程相關的東西(比如獲取一個保護一些共享資源的互斥鎖)的檢查。預連接代碼可能是這樣的:

mov eax,__pthread_key_create 
    test rax,rax 
    jz .skip_mutex_init 
    call __pthread_init_some_mutex 
.skip_mutex_init: 
    mov rax, 0xffffffffffffff60 
    sub rbx,r15 
    add QWORD PTR fs:[rax],rbx` 

在那裏你看到決心NULL指針所有__pthread符號。當然,最終的代碼是非常愚蠢的 - 編譯器不知道鏈接器是否將被調用-lpthread,並且鏈接器只是執行愚蠢的替換 - 再次運行優化器太晚了(除非啓用了LTO,但這是一個完全不同的遊戲)。

您可以看到自己類似的圖案playing with the compiler explorer:嘗試啓用/禁用鏈接完整的二進制文件(右邊的按鈕和11010標題),並在命令行上添加/刪除-pthread。現在

,我沒能精確再現你的結果,但可能是來自不同版本的libstdc++被使用,或者在你的代碼中使用了不同的線程感知組件(我只是嘗試用std::mutexstd::shared_ptr) 。

+0

不,調用0x0 '只是調用下一條指令,而不是空指針。這是已經靜態鏈接的程序(gdb disasm的輸出)的一個失敗。 – vladon

+0

我不確定,IIRC通常會將gdb轉儲爲'call 0x3ad2e6 <+0>',類似於上面的相對跳轉。不過,如果像你說的那樣,它看起來像手寫代碼來阻止反編譯器等等 - 在函數內部插入虛假調用本身會破壞啓發式規則以重建函數入口點/塊。 –

+0

哦,廢話,是的,這是一個NULL指針加載,而不是'mov eax,imm32'。我只是不習慣GDB版本的Intel語法。 'objdump'將會打印出'DWORD PTR:0'。 (@vladon) –