คำสั่ง CFI ใน Gnu Assembler (GAS) ใช้ทำอะไร


118

ดูเหมือนจะมีคำสั่ง .CFI หลังจากที่ทุกสายและยังมีหลากหลายพันธุ์อดีตเหล่านี้. .cfi_startproc, .cfi_endprocฯลฯ .. เพิ่มเติมได้ที่นี่

    .file   "temp.c"
    .text
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
.globl func
    .type   func, @function
func:
.LFB1:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    %edi, -4(%rbp)
    movl    %esi, %eax
    movb    %al, -8(%rbp)
    leave
    ret
    .cfi_endproc
.LFE1:
    .size   func, .-func
    .ident  "GCC: (Ubuntu 4.4.1-4ubuntu9) 4.4.1"
    .section    .note.GNU-stack,"",@progbits

ฉันไม่ได้รับวัตถุประสงค์ของสิ่งเหล่านี้


3
คำอธิบายcfiคำแนะนำGNU AS ที่นี่
Paschalis

ที่เกี่ยวข้อง: จะลบ "เสียง" ออกจากเอาต์พุตการประกอบ GCC / เสียงดังได้อย่างไร หากคุณต้องการเพียงคำแนะนำโดยไม่มีคำสั่ง วิธีที่ดีคือวางโค้ดของคุณบนgcc.godbolt.orgเพื่อดูเอาต์พุต asm ที่กรองแล้วอย่างดีจากคอมไพเลอร์รุ่นต่างๆ (รวมถึงที่ไม่ใช่ x86) โดยมีการเน้นสีเพื่อให้ตรงกับบรรทัดซอร์สกับบล็อก asm
Peter Cordes

คำตอบ:


70

ฉันรู้สึกว่ามันย่อมาจากCall Frame Informationและเป็นส่วนขยาย GNU AS เพื่อจัดการ call frames จากDeveloperWorks :

ในบางสถาปัตยกรรมต้องจัดการข้อยกเว้นด้วยคำสั่ง Call Frame Information คำสั่งเหล่านี้ใช้ในแอสเซมบลีเพื่อจัดการข้อยกเว้นโดยตรง คำสั่งเหล่านี้พร้อมใช้งานบน Linux บน POWER หากด้วยเหตุผลใด ๆ (ความสามารถในการเคลื่อนย้ายฐานรหัสเป็นต้น) GCC สร้างข้อมูลการจัดการข้อยกเว้นไม่เพียงพอ

ดูเหมือนว่าสิ่งเหล่านี้ถูกสร้างขึ้นในบางแพลตฟอร์มขึ้นอยู่กับความจำเป็นในการจัดการข้อยกเว้น

หากคุณกำลังมองหาที่จะปิดการใช้งานเหล่านี้โปรดดูคำตอบของดาวิด


5
นอกจากนี้คุณสามารถพูดคำเกี่ยวกับ. LFB0, .LFB1, .LFE0, .LFE1
กรงเล็บ

@claws - เป็นป้ายกำกับที่สร้างโดยคอมไพเลอร์ (ดังที่คุณเห็นจาก:) ดูstackoverflow.com/a/15285058/4294399
Calculuswhiz

144

หากต้องการปิดใช้งานให้ใช้ตัวเลือก gcc

-fno-asynchronous-unwind-tables

-fno-dwarf2-cfi-asm อาจจำเป็นด้วย


12
-fno-dwarf2-cfi-asmอาจจำเป็นด้วย
technosaurus

หากคุณปิดการใช้งานสำหรับเอาต์พุต asm ที่มนุษย์อ่านได้โปรดดูวิธีการลบ "สัญญาณรบกวน" จากเอาต์พุตการประกอบ GCC / clang สำหรับตัวเลือกและเทคนิคที่เป็นประโยชน์อื่น ๆ
Peter Cordes

30

คำสั่ง CFI ใช้สำหรับการดีบัก ช่วยให้ดีบักเกอร์คลายสแต็ก ตัวอย่างเช่น: ถ้าโพรซีเดอร์ A เรียกโพรซีเดอร์ B ซึ่งเรียกโพรซีเดอร์ทั่วไป C. โพรซีเดอร์ C ล้มเหลว ตอนนี้คุณอยากรู้ว่าใครเรียก C จริงๆแล้วคุณอาจจะอยากรู้ว่าใครเรียก B

ดีบักเกอร์สามารถคลายสแต็กนี้ได้โดยใช้ตัวชี้สแต็ก (% rsp) และรีจิสเตอร์% rbp อย่างไรก็ตามจำเป็นต้องรู้วิธีค้นหา นั่นคือที่มาของคำสั่ง CFI

movq    %rsp, %rbp
.cfi_def_cfa_register 6

ดังนั้นบรรทัดสุดท้ายที่นี่บอกว่า "ที่อยู่เฟรมการโทร" อยู่ในการลงทะเบียน 6 (% rbp)


2
แต่ข้อยกเว้นในการจัดการการใช้ cfi ควรจะบ่อยกว่าการดีบักฉันคิดว่า
osgx

6
CFA ย่อมาจาก "ที่อยู่เฟรมมาตรฐาน" ดูที่นี่ .
Cameron


1
คำสั่ง CFI ช่วยให้สามารถคลายสแต็กได้แม้กระทั่งสำหรับโค้ดที่คอมไพล์ด้วย-fomit-frame-pointerเป็นทางเลือกอื่นสำหรับ RBP (ซึ่งจะเปิดโดยค่าเริ่มต้นด้วย gcc หรือ clang -O1และสูงกว่า) ใช้โดยการจัดการข้อยกเว้น C ++ เช่นเดียวกับ debuggers / profilers ในโค้ดที่มีตัวชี้เฟรม RBP แบบเดิมค่า RBP ปัจจุบันจะชี้ไปที่ค่า RBP ที่บันทึกไว้เสมอและชี้ไปที่ค่าก่อนหน้าซึ่งสร้างรายการที่เชื่อมโยง ไม่จำเป็นต้องมี CFI ในกรณีนั้น (แม้ว่าในฟังก์ชันที่ใช้ตัวชี้เฟรม CFI cfa_register จะหลีกเลี่ยงการต้องการข้อมูลเมตาเพิ่มเติมสำหรับการเปลี่ยนแปลง RSP ทุกครั้งเช่นที่คุณกำลังแสดงอยู่)
Peter Cordes

2

ในการปิดใช้งานสิ่งเหล่านี้จำเป็นต้องใช้ g ++ -fno-exceptionsพร้อมกับที่กล่าวไว้ก่อนหน้านี้-fno-asynchronous-unwind-tablesโดยที่คุณไม่ได้ใช้ข้อยกเว้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.