เราสร้างไฟล์ ELF พร้อมข้อมูลภาษี (DWARF) ด้วยตนเอง (สำหรับไมโครคอนโทรลเลอร์ ARM) จัดรูปแบบนามสกุลไฟล์ ELF และ PE EXE Elf
เวอร์ชันที่มี TOC ที่ดีและมีเนื้อหามากมาย: http://www.cirosantilli.com/elf-hello-world (กด 30k char exchange ที่นี่)
มาตรฐาน
ELF มอบให้โดย LSB:
- หลักทั่วไป: http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/elf-generic.html
- คอร์ AMD64: http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-AMD64/LSB-Core-AMD64/book1.html
LSB มีความสำคัญที่ต้องพึ่งพามาตรฐานอื่นที่มีส่วนขยายเล็กน้อย ยกเว้น:
- System V ABI 4.1 (1997) http://www.sco.com/developers/devspecs/gabi41.pdf ไม่ใช่ 64 บิต ต้องการหมายเลขวิเศษที่สงวนไว้ สำหรับไฟล์หลัก
- System V ABI Update DRAFT 17 (2003) http://www.sco.com/developers/gabi/2003-12-17/contents.html เพิ่ม 64 บิต เพียงอัปเดตส่วน 4 และ 5 ของเอกสารด้านหน้า: เย็บแผลด้วยคางและถามเหมือนก่อนหน้านี้
สถาปัตยกรรมเฉพาะ:
- IA-32: http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-IA32/LSB-Core-IA32/elf-ia32.html ส่วนใหญ่ที่ http://www.sco.com/developers /devspecs /abi386-4.pdf
- AMD64: http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-AMD64/LSB-Core-AMD64/elf-amd64.html ส่วนใหญ่จะอยู่ที่ http://www.x86-64.org/ documentation/ abi.pdf
ทั่วไป (ละเมิด SCO):
สามารถดูบทสรุปที่ดีกว่าได้ที่:
คุณสามารถดูโครงสร้างนี้เพื่อหาวิธีการที่มีประโยชน์เพิ่มเติม เช่น readelf และ objdump
สร้างก้น
ให้ฉันแยกย่อยตัวอย่างขั้นต่ำที่ Linux x86-64 ชนะ:
ส่วน .data hello_world db "Hello world!", 10 hello_world_len เท่ากับ $ - ส่วน hello_world .text
รวบรวมมาให้ช่วย
Nasm -w+all -f elf64 -o "hello_world.o" "hello_world.asm" ld -o "hello_world.out" "hello_world.o"
- นาสเอ็ม 2.10.09
- Binutils เวอร์ชัน 2.24 (แทนที่ ld)
- อูบุนตู 14.04
เราไม่ได้เอาชนะโปรแกรม C เพื่อให้เราสามารถลดความซับซ้อนของการวิเคราะห์ซึ่งจะเท่ากับ 2 :-)
16 อาการไบนารี
hd hello_world.o hd hello_world.outโครงสร้างไฟล์ส่วนกลาง
ไฟล์ ELF ประกอบด้วยส่วนต่อไปนี้:
ส่วนหัวของเอลฟ์ ระบุตำแหน่งของตารางส่วนหัวที่แบ่งและตารางส่วนหัวของโปรแกรม
ตารางหัวเรื่องในหน่วยงาน (จำเป็นในภาษาของไฟล์ไอคอน) ผิวหนังอาจเป็นส่วนหัวของส่วน e_shnum;
N ดิวิชั่น N<= e_shnum (необязательно в исполняемом файле)
ตารางส่วนหัวของโปรแกรม (สำหรับเลือกไฟล์เท่านั้น) บางส่วนอาจเป็นส่วนหัวของโปรแกรม e_phnum บางส่วนระบุตำแหน่งของส่วน
N ส่วน s N<= e_phnum (необязательно в исполняемом файле)
ลำดับของส่วนเหล่านี้ไม่ได้รับการแก้ไข: หนึ่งส่วนคงที่ - ส่วนหัวของ ELF ซึ่งอาจเป็นส่วนแรกในไฟล์: เอกสารส่วนกลางดูเหมือนจะเป็น:
ส่วนหัวของเอลฟ์
วิธีที่ง่ายที่สุดในการพาดหัวข่าว:
readelf -h hello_world.o readelf -h hello_world.out
ไบต์ในไฟล์วัตถุ:
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF..........| 00000010 01 00 3e 00 01 00 00 00 00 00 00 00 00 00 00 00 |..>............| 00000020 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 | [ป้องกันอีเมล]| 00000030 00 00 00 00 40 00 00 00 00 00 40 00 07 00 03 00 |[ป้องกันอีเมล]@.....|
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF..........| 00000010 02 00 3e 00 01 00 00 00 b0 00 40 00 00 00 00 00 |..> [ป้องกันอีเมล]| 00000020 40 00 00 00 00 00 00 00 10 01 00 00 00 00 00 00 |@...............| 00000030 00 00 00 00 40 00 38 00 02 00 40 00 06 00 03 00 |[ป้องกันอีเมล]@.....|
โครงสร้างยื่น:
Typedef struct ( unsigned char e_ident; Elf64_Half e_type; Elf64_Half e_machine; Elf64_Word e_version; Elf64_Addr e_entry; Elf64_Off e_phoff; Elf64_Off e_shoff; Elf64_Word e_flags; Elf64_Half e_ehsize; Elf64_Half e_phentsize; Elf64_Half e_phnum; Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; ) Elf64_Ehdr;
สลายตัวด้วยตนเอง:
0 0: EI_MAG = 7f 45 4c 46 = 0x7f "E", "L", "F": เลขวิเศษเอลฟ์
0 4: EI_CLASS = 02 = ELFCLASS64: เอลฟ์ 64 บิต
0 5: EI_DATA = 01 = ELFDATA2LSB: ข้อมูลกลุ่มใหญ่
0 6: EI_VERSION = 01: เวอร์ชันรูปแบบ
0 7: EI_OSABI (เฉพาะในปี 2546) = 00 = ELFOSABI_NONE: ไม่มีนามสกุล
08: EI_PAD = 8x 00: ไบต์ที่สงวนไว้ มีความผิด แต่ตั้งค่าเป็น 0
1 0: e_type = 01 00 = 1 (ตัวท้ายใหญ่) = ET_REl: รูปแบบที่จะย้าย
ไฟล์มี 02 00 สำหรับ ET_EXEC
1 2: e_machine = 3e 00 = 62 = EM_X86_64: สถาปัตยกรรม AMD64
1 4: e_version = 01 00 00 00: สามารถเป็น 1
1 8: e_entry = 8x 00: จุดเริ่มต้นของที่อยู่ของรายการหรือ 0 ดังนั้นจึงไม่ zastoovuetsya สำหรับไฟล์วัตถุเนื่องจากไม่มีจุดเริ่มต้น
ไฟล์มี b0 00 40 00 00 00 00 00 สิ่งที่ต้องทำ: เราสามารถติดตั้งอะไรได้บ้าง? เคอร์เนลที่นี่กำหนด IP โดยไม่มีค่ากลางไม่ยากที่จะตั้งโปรแกรม
2 0: e_phoff = 8x 00: ใช้ตารางส่วนหัวของโปรแกรม 0 แต่ไม่ใช่
40 00 00 00 สำหรับไฟล์ ดังนั้น vin จะเริ่มต้นทันทีหลังจากส่วนหัวของ ELF
2 8: e_shoff = 40 7x 00 = 0x40: ใช้เพื่อแยกไฟล์ตารางส่วนหัว 0 มิฉะนั้นจะไม่
3 0: e_flags = 00000000 สิ่งที่ต้องทำ พิเศษสำหรับอาร์ค
3 4: e_ehsize = 4000: ขนาดของหัวเอลฟ์ ทำไมต้องสนาม? คุณจะเปลี่ยนได้อย่างไร?
3 6: e_phentsize = 00 00: ขนาดส่วนหัวของสกินโปรแกรม, 0 แต่ไม่ใช่
38 00 สำหรับไฟล์ที่ถูกแฮ็ก: ความยาวของไฟล์คือ 56 ไบต์
3 8: e_phnum = 0000: จำนวนรายการส่วนหัวของโปรแกรม 0 ซึ่งไม่ใช่
02 00 สำหรับไฟล์ที่เชื่อมโยง: є 2 รายการ
3 A: e_sentsize และ e_shnum = 40 00 07 00: heading size เพื่อแบ่งเรคคอร์ดจำนวนนี้
ตารางส่วนหัว
อาร์เรย์ของโครงสร้าง Elf64_Shdr
บันทึกหนังเรียกข้อมูลเมตาเกี่ยวกับแผนกนี้
e_shoff ของส่วนหัว ELF ให้ตำแหน่งสแปม 0x40
e_shentsize และ e_shnum จากส่วนหัวของ ELF ดูเหมือนว่าเรามี 7 รายการ ผิวลิ่ม 0x40
อีกครั้ง ตารางรับไบต์จาก 0x40 ถึง 0x40 + 7 + 0x40 - 1 = 0x1FF
ตั้งชื่อส่วนที่สงวนไว้สำหรับการร้องเพลงประเภทต่างๆ เช่น http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html#special_sections .text ประเภทที่ต้องการ SHT_PROGBITS และ SHF_ALLOC + SHF_EXECINSTR
readelf -S hello_world.o:
มีส่วนหัว 7 ส่วนเริ่มต้นที่ออฟเซ็ต 0x40: ส่วนหัว: ชื่อประเภทที่อยู่ออฟเซ็ตขนาด entsize ธงข้อมูลการเชื่อมโยง [0] NULL000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002] .text PROGBITS 0000000000000000 00000210 0000000000000027 0000000000000000 AX 0 0 16 [ 3] .shstrtab STRTAB 0000000000000000 00000240 0000000000000032 0000000000000000 0 0 1 [ 4] .symtab SYMTAB 0000000000000000 00000280 00000000000000a8 0000000000000018 5 6 4 [ 5] .strtab STRTAB 0000000000000000 00000330 0000000000000034 0000000000000000 0 O (ต้องการการประมวลผล OS เพิ่มเติม) o (เฉพาะ OS), p (เฉพาะโปรเซสเซอร์)
struct ในรูปแบบสกิน:
โครงสร้าง Typedef ( Elf64_Word sh_name; Elf64_Word sh_type; Elf64_Xword sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; Elf64_Xword sh_size; Elf64_Word sh_link; 64;
กระจาย
กระจายไปยังดัชนี 0
ย้ายจากไบต์จาก 0x40 เป็น 0x7F
ส่วนแรกมีเสน่ห์เสมอ: http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html
นอกจากนี้ จำนวนของส่วน SHN_LORESERVE (0xff00) หรือมากกว่านั้น e_shnum อาจมีค่า SHN_UNDEF (0) และจำนวนระเบียนในตารางส่วนหัวของการกระจายจะถูกเก็บไว้ในฟิลด์ sh_size ของส่วนหัวของพาร์ติชันด้วย ดัชนี 0 (บันทึกสมาชิก sh_size ด้วย)
ส่วนรูปที่ 4-7: ดัชนีส่วนพิเศษสำหรับส่วนมายากลอื่นๆ
ในดัชนี 0 SHT_NULL є obov'yazykovim Chi іsnuyet іnshі vidi vikoristannya: อะไรคือความเสียหายในการแยกวิเคราะห์ SHT_NULL ใน ELF? ?
.data แยก
ข้อมูล - ส่วนที่ 1:
00000080 01 00 00 00 01 00 00 00 03 00 00 00 00 00 00 00 |................| 00000090 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 |................| 000000a0 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000b0 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
80 4: sh_type = 01 00 00 00: SHT_PROGBITS: แทนที่จะแจกจ่ายงานที่ไม่ใช่ของ ELF เช่นเดียวกับที่โปรแกรมตีความโยคะ ไม่เป็นไรเพราะ .data
80 8: sh_flags = 03 7x 00: SHF_ALLOC และ SHF_EXECINSTR: http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html#sh_flags ตามที่กำหนดโดยการกระจาย
90 0: sh_addr = 8x 00: ในที่อยู่เสมือนนี้จะถูกวางตำแหน่งในตอนท้ายของวัน ดังนั้นจึงไม่มีตำแหน่ง
90 8: sh_offset = 00 02 00 00 00 00 00 00 = 0x200: จำนวนไบต์ในตอนเริ่มต้นของโปรแกรมถึงไบต์แรกในการกระจายนี้
a0 0: sh_size = 0d 00 00 00 00 00 00 00
ดังนั้นใช้ 0xD ไบต์เริ่มต้นด้วย sh_offset 200, mi bachimo:
00000200 48 65 6c 6c 6f 20 77 6f 72 6c 64 21 0a 00 |สวัสดีชาวโลก!.. |
อะฮ่า! Otzhe แถวของเรา "สวัสดีชาวโลก!" รู้ในการกระจายข้อมูลตามที่เรากล่าวไว้ tse NASM
เมื่อเราดูแบบ HD เสร็จ เราจะเห็นดังนี้:
Readelf-x.data สวัสดี_world.o
อันไหนที่จะป้อน:
ดัมพ์เลขฐานสิบหกของส่วน ".data": 0x00000000 48656c6c 6f20776f 726c6421 0a สวัสดีชาวโลก!.
NASM กำหนดวันพลังงานสำหรับแผนกซึ่งถูกวางไว้อย่างน่าอัศจรรย์ก่อน: ข้อมูล: http://www.nasm.us/doc/nasmdoc7.html#section-7.9.2
นอกจากนี้ ให้ความสนใจกับความจริงที่ว่ามีการเลือกผิด: คอมไพเลอร์ C ที่ดีโดยการวางแถวใน .rodata เพื่อแทนที่บางสิ่งที่มีไว้สำหรับการอ่านเท่านั้น และเพื่อให้สามารถปรับแต่งระบบปฏิบัติการต่อไปได้
a0 8: sh_link และ sh_info = 8x 0: อย่าหยุดที่ประเภทของการกระจาย http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html#special_sections
b0 0: sh_addralign = 04 = สิ่งที่ต้องทำ: ต้องการเปลี่ยนแปลงหรือไม่ มีเป้าหมายสำหรับ sh_addr และสำหรับสัญลักษณ์ที่อยู่ตรงกลางของ sh_addr หรือไม่
b0 8: sh_entsize = 00 = แยกไม่ล้างแค้นโต๊ะ ยักโช! = 0 ซึ่งหมายความว่ามีการแจกจ่ายตารางบันทึกขนาดคงที่ ไฟล์ใดควรมีลิงก์ readelf แต่มีที่ว่างสำหรับการแจกแจง .symtab และ .rela.text
ที่นี่ 1 เพื่อบอกว่าอักขระตัวแรกของส่วนนี้เริ่มต้นด้วยอักขระตัวแรกของส่วนและสิ้นสุดด้วยอักขระตัวแรก NUL การตั้งค่า row.data
ข้อมูล - ชื่อหนึ่งของการกระจาย เนื่องจากอาจเป็นค่าเดียวกัน http://www.sco.com/developers/gabi/2003-12-17/ch4.strtab.html
ในส่วนเหล่านี้ ข้อมูลเริ่มต้นจะถูกบันทึก เพื่อช่วยในการสร้างอิมเมจของหน่วยความจำของโปรแกรม
.text แยก
ตอนนี้ถ้าเราแบ่งส่วนด้วยมือให้บัณฑิตและบัณฑิต readelf -S ของส่วนอื่น ๆ
ชื่อ ประเภท ที่อยู่ ขนาดออฟเซ็ต EntSize แฟล็ก ข้อมูลลิงก์ จัดตำแหน่ง [ 2 ] .text PROGBITS 0000000000000000 00000210 000000000000020 000
ข้อความจะถูกเขียนหากไม่สามารถเขียนได้: ดังนั้นเราจึงสามารถลองเขียน segfaults ของ Linux ได้ เราสงสัยว่าทำไมเราถึงมีรหัส:
Objdump -d hello_world.o
Hello_world.o: รูปแบบไฟล์ elf64-x86-64 การแยกส่วน .text: 0000000000000000<_start>: 0: b8 01 00 00 00 mov $0x1,%eax 5: bf 01 00 00 00 mov $0x1,%edi a: 48 be 00 00 00 00 00 movabs $0x0,%rsi 11:00 0 0d 00 00 00 mov $0xd,%edx 19:0f 05 syscall 1b:b8 3c 00 00 00 mov $0x3c,%eax 20:bf 00 00 00 00 mov $0x0,%edi 25:0
เราจะ grep b8 01 00 00 บน hd ได้อย่างไร เราจะเห็นเฉพาะใน 00000210 ตามที่กล่าวไว้ในการกระจายนี้ І rozmir dorivnyuє 27 ซึ่งได้รับการยืนยันเช่นกัน นั่นเป็นเหตุผลที่เราสามารถพูดคุยเกี่ยวกับการแบ่งที่ถูกต้อง
ดูเหมือนว่ารหัสที่ถูกต้อง: a write ตามด้วย exit
Naytsіkavіsha part - แถว a ซึ่งจะปล้น:
เคลื่อนย้าย $0x0,%rsi
ส่งแถวที่อยู่ไปยังวิกิระบบ ในเดนมาร์ก ชั่วโมง 0x0 เป็นเพียง zapovnyuvachem หลังจากวางสาย จะมีการเปลี่ยนแปลงโยคะ:
4000ba: 48 be d8 00 60 00 00 movabs $0x6000d8,%rsi
การแก้ไขนี้สามารถทำได้ผ่านข้อมูลการแจกแจง rela.text
SHT_STRTAB
พาร์ติชันที่มี sh_type == SHT_STRTAB เรียกว่าตารางแถว
ดังนั้นพวกไวโคริสต์จึงถูกแบ่งออกเป็นฝ่ายอื่น ๆ ถ้าเรียงแถวของพวกไวโคริสต์ ส่วน "วิคตอเรีย" พูดว่า:
- ช่างเป็นแถวของ vikoristovuyut กลิ่นเหม็น
- ดัชนีของตารางของทั้งแถวคืออะไร แถวเริ่มต้นที่ใด
ตัวอย่างเช่น เราสามารถสร้างตารางแถว วิธีล้างแค้น: สิ่งที่ต้องทำ: คุณต้องเริ่มด้วย \0 อะไร
ข้อมูล: \0 abc \0 d e f \0 ดัชนี: 0 1 2 3 4 5 6 7 8
І yakscho іnshiy razdіlต้องการที่จะชนะแถว d e f กลิ่นเหม็นของการตำหนิเพื่อระบุในดัชนี 5 ของ tsgo razdіlu (ตัวอักษร d)
ดูตารางแถว:
- .shstrtab
- .strtab
.shstrtab
ประเภทพาร์ติชัน: sh_type == SHT_STRTAB
Zagalne im'ya: แถวชื่อเรื่องถูกแบ่งออก
ฉันแชร์แล้ว shstrtab ถูกสงวนไว้ มาตรฐานมี:
Tsey แยกเพื่อล้างแค้นชื่อแยก
สาขาใดควรมีฟิลด์ e_shstrnd ของส่วนหัว ELF
ดัชนีแถวของส่วนนี้ระบุโดยฟิลด์ sh_name ของส่วนหัวของส่วน ซึ่งระบุแถว
สาขาใดที่ไม่ได้เปิดใช้งาน SHF_ALLOC จะใช้งานไม่ได้กับโปรแกรมที่ชนะ
Readelf-x.shstrtab สวัสดี_world.o
Hex dump of section ".shstrtab": 0x00000000 002e6461 7461002e 74657874 002e7368 ..data..text..sh 0x00000010 73747274 6162002e 73796d74 6162002e strtab..symtab.. 0x00000020 73747274 6162002e 72656c61 2e746578 strtab..rela.tex 0x00000030 7400 t.
ข้อมูลที่คุณเผยแพร่อาจแก้ไขรูปแบบ: http://www.sco.com/developers/gabi/2003-12-17/ch4.strtab.html
ในขณะที่เราประหลาดใจกับชื่อของแผนกอื่นๆ จะดีกว่าที่กลิ่นเหม็นทั้งหมดจะล้างแค้นให้กับตัวเลข เป็นต้น section.text อาจหมายเลข 7 .
จากนั้นแถวสกินจะสิ้นสุดลงหากพบอักขระ NUL ตัวแรก อักขระ 12 \ 0 ในครั้งต่อไป ข้อความ \ 0 .
.symtab
ประเภทพาร์ติชัน: sh_type == SHT_SYMTAB
ชื่อสามัญ: ตารางสัญลักษณ์.
มีนัยสำคัญกลับไปกลับมาว่า:
- sh_link = 5
- sh_info=6
ในส่วน SHT_SYMTAB ตัวเลขหมายความว่า:
- แถว
- วิธีการตั้งชื่อสัญลักษณ์, เปลี่ยนจากสาขา 5, .strtab
- ข้อมูลการย้ายจะถูกซื้อใหม่ที่สาขา 6, .rela.text
เครื่องมือที่ดีในระดับสูงสำหรับการแยกแยะส่วนนี้:
Nm hello_world.o
อันไหนคือ:
0000000000000000 T _start 0000000000000000d hello_world 000000000000000d a hello_world_len
อย่างไรก็ตาม Tse เป็นการแสดงออกถึงระดับสูงซึ่งไม่มีการละเว้นประเภทของสัญลักษณ์และสัญลักษณ์ที่กำหนด สามารถวิเคราะห์รายละเอียดเพิ่มเติมเพื่อขอความช่วยเหลือ:
Readelf -s hello_world.o
อันไหนคือ:
ตารางสัญลักษณ์ ".symtab" มี 7 รายการ: NUM: ค่าขนาดประเภทประเภทการผูก vis ndx ชื่อ 0: 0000000000000000 0 Notype ท้องถิ่นเริ่มต้นและเริ่มต้น 1: 0000000000000000 0 ไฟล์ท้องถิ่นเริ่มต้น abs hello_world.asm 2: 00000000000000 0 ส่วน ค่าเริ่มต้นในท้องถิ่น 2 4: 0000000000000000 0 ค่าเริ่มต้นในท้องถิ่นที่ไม่ใช่ประเภท 1 hello_world 5: 000000000000000d 0 ค่าเริ่มต้นในท้องถิ่นที่ไม่ใช่ประเภท ABS hello_world_len 6: 00000000000
รูปแบบตารางไบนารีมีบันทึกไว้ที่ http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html
Readelf-x.symtab สวัสดี_world.o
คุณให้อะไร:
ดัมพ์เลขฐานสิบหกของส่วน ".symtab": 0x00000000 00000000 00000000 00000000 00000000 ................ 0x00000010 00000000 00000000 01000 .... . 0x00000020 00000000 000000 00000000 000000 000000 .......................... 0x00000050 00000000 00000000 00000000 00000000 ............ .... 0x00000060 11000000 00000100 00000000 000 ...... 0x00000070 00000000 0000000000 ................ 0x00000080 0D000000000000000000..... 0x000000a0 00000000 00000000 ....... .
ประเภทการบันทึก:
Typedef struct ( Elf64_Word st_name; unsigned char st_info; unsigned char st_other; Elf64_Half st_shndx; Elf64_Addr st_value; Elf64_Xword st_size; ) Elf64_Sym;
เช่นเดียวกับในตารางการแบ่ง รายการแรกเป็นการกุศลและกำหนดเป็นค่าว่างคงที่
บันทึก 1 พฤษภาคม ELF64_R_TYPE == STT_FILE ELF64_R_TYPE คือสามตัวที่อยู่ตรงกลางของ st_info
การวิเคราะห์ไบต์:
10 8: st_name = 01000000 = ตัวละคร 1 st.strtab ซึ่งขึ้นอยู่กับฝ่ายรุก \0 เพื่อปล้น hello_world.asm
ส่วนของไฟล์ข้อมูลนี้สามารถแบ่งออกเป็นตัวเชื่อมโยงซึ่งจะกำหนดว่าเซ็กเมนต์ควรไปอย่างไร
10 12: st_info = 04
บิต 0-3 = ELF64_R_TYPE = Type = 4 = STT_FILE: เมตาเรกคอร์ดหลัก - แท็ก st_name เพื่อให้ตรงกับชื่อไฟล์ที่สร้างโดยไฟล์วัตถุนี้
บิต 4-7 = ELF64_ST_BIND = การผูก = 0 = STB_LOCAL ค่าที่จำเป็นสำหรับ STT_FILE
10 13: st_shndx = ตารางสัญลักษณ์ ส่วนหัวของตาราง ดัชนี = f1ff = SHN_ABS จำเป็นสำหรับ STT_FILE
20 0: st_value = 8x 00: จำเป็นสำหรับค่าสำหรับ STT_FILE
20 8: st_size = 8x 00: ไม่เห็นขนาด
ทีนี้จาก readelf ผมจะรีบตีความ
STT_SECTION
มีสององค์ประกอบดังกล่าว หนึ่งชี้ไปที่ .data และอีกองค์ประกอบหนึ่งชี้ไปที่ .text (ดัชนีแบ่ง 1 และ 2)
จำนวน: ค่า ขนาด ประเภท เชื่อมโยง Vis Ndx ชื่อ 2: 0000000000000000 0 ส่วน ค่าเริ่มต้นในท้องถิ่น 1 3: 0000000000000000 0 ส่วน ค่าเริ่มต้นในท้องถิ่น 2
TODO เมตาคืออะไร?
STT_NOTYPE
จากนั้นป้อนอักขระที่สำคัญที่สุด:
Num: ค่า ขนาด ประเภท ผูก Vis Ndx ชื่อ 4: 0000000000000000 0 ค่าเริ่มต้นท้องถิ่น NOTYPE 1 hello_world 5: 000000000000000d 0 ค่าเริ่มต้นท้องถิ่น NOTYPE ABS hello_world_len 00 0
hello_world ตั้งอยู่ใน distribution.data (ดัชนี 1) ค่า ค่า 0: ตรวจสอบไบต์แรกของการกระจาย
เริ่มตั้งค่าการเปิดเผยของ GLOBAL ตามที่เราเขียน:
global_start
ที่ NASM ไม่จำเป็น เศษสามารถเห็นเป็นจุดเริ่มต้น ในมุมมอง C สำหรับป้ายส่งเสริมการขาย NASM є local
hello_world_len อ้างถึง st_shndx == SHN_ABS == 0xF1FF พิเศษ
0xF1FF ถูกเลือกในลักษณะที่จะไม่โกงสาขาอื่นๆ
st_value == 0xD == 13 แล้วแต่ว่าจะมีค่าใด ซึ่งเราได้บันทึกไว้ที่นั่นสำหรับการเลือก: ด้านหลังของแถว Hello World! .
Tse หมายความว่าการเคลื่อนไหวไม่สอดคล้องกับค่า: เป็นค่าคงที่
มันไม่ใช่การเพิ่มประสิทธิภาพขนาดใหญ่ วิธีการทำงานของแอสเซมเบลอร์สำหรับเราที่สามารถรองรับเอลฟ์ได้
Yakby mi vikoristovuvali ที่อยู่ hello_world_len ในสถานที่ใด ๆ แอสเซมเบลอร์จะไม่ zmіg bi pomiti yogo yak SHN_ABS และตัวเชื่อมโยงจะถูกย้ายเพิ่มเติม
SHT_SYMTAB สำหรับไฟล์ที่เป็นไอคอน
สำหรับการโปรโมต NASM ให้วาง .symtab ในไฟล์ที่เป็นไอคอน
Tse vikoristovuєtsya น้อยลงสำหรับ nagodzhennya หากไม่มีสัญลักษณ์ เราตาบอดสนิทและอาจออกแบบทุกอย่างใหม่
คุณสามารถดูได้เพื่อขอความช่วยเหลือ objcopy และดาวน์โหลดไฟล์ทั้งหมดจะใช้งานได้ ไฟล์ดังกล่าวที่เป็นไอคอนเรียกว่าไฟล์แยกไอคอน
.strtab
กำจัดแถวสำหรับสัญลักษณ์ตาราง
ซึ่งการแจกแจงมี sh_type == SHT_STRTAB
แสดงใน sh_link == 5 การกระจาย
Readelf-x.strtab สวัสดี_world.o
Hex dump of section ".strtab": 0x00000000 0068656c 6c6f5f77 6f726c64 2e61736d .hello_world.asm 0x00000010 0068656c 6c6f5f77 6f726c64 0068656c .hello_world.hel 0x00000020 6c6f5f77 6f726c64 5f6c656e 005f7374 lo_world_len._st 0x00000030 61727400 art.
ซึ่งหมายความว่ามีการแลกเปลี่ยน ELF ซึ่งมีการเปลี่ยนแปลงทั่วโลกซึ่งเป็นไปไม่ได้ที่จะลบอักขระ NUL
.rela.ข้อความ
ประเภทการกระจาย: sh_type == SHT_RELA
ชื่อหัวเรื่อง : แยกย้าย.
Rela.text ตอบกลับข้อมูลของการย้ายตำแหน่ง ซึ่งถูกกำหนดให้เป็นที่อยู่ที่จะเปลี่ยนแปลง หากพบไฟล์ที่เหลือของ Hit tse vkazuєบนไบต์ของพื้นที่ข้อความ, yakіmаyut buti zmіnіnі, ถ้า zv'yazuvannya vіdbuvaєєєє zaznachennymi їїїїїїїїїїїї
ในไวน์หลักฉันเขียนข้อความของวัตถุใหม่เพื่อล้างแค้นที่อยู่ของ 0x0 zapovnyuvacha:
A:48 รู 00 00 00 00 00 movabs $0x0,%rsi 11:00 00 00
ไปที่รหัสที่ถูกแฮ็กจริงเพื่อลบ 0x6000d8 ที่เหลือ:
4000ba: 48 เป็น d8 00 60 00 00 movabs $0x6000d8,%rsi 4000c1:00 00 00
ระบุ Sh_info = 6
readelf -r hello_world.o ใช่:
ส่วนการย้ายตำแหน่ง ".rela.text" ที่ offset 0x3b0 offset 1 point: Offset Info Type Sym. ค่าซิม ชื่อ + เพิ่ม 00000000000c 000200000001 R_X86_64_64 0000000000000000 .data + 0
การแจกจ่ายไม่ได้ขึ้นอยู่กับไฟล์ที่กำลังตรวจสอบ
ไบต์จริง:
00000370 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 |................| 00000380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
ตัวแทนโครงสร้าง:
โครงสร้าง Typedef ( Elf64_Addr r_offset; Elf64_Xword r_info; Elf64_Sxword r_addend; ) Elf64_Rela;
- ELF64_R_TYPE = 0x1: ค่าที่จะฝากเป็นสถาปัตยกรรมที่แน่นอน
- ELF64_R_SYM = 0x2: ดัชนีแบ่งพาร์ติชัน, ที่อยู่, volume.data ซึ่งมีดัชนี 2
- S: ค่าอักขระในอ็อบเจกต์ไฟล์คือ 0 ที่นี่ ดังนั้นเราสามารถตั้งค่าเป็น 00 00 00 00 00 00 00 00 s movabs $0x0,%rsi
- a: เพิ่มลงในฟิลด์ r_added
370 0: r_offset = 0xC: ที่อยู่ไปยัง address.text ที่อยู่ที่จะเปลี่ยนแปลง
370 8: r_info = 0x200000001. หมอก 2 ช่อง:
AMD64 ABI กล่าวว่าประเภท 1 เรียกว่า R_X86_64_64 และ VIN นั้นแสดงถึงการดำเนินการ S+A de:
ที่อยู่ Tsya จะถูกเพิ่มในการแจกจ่ายโดยการย้ายถิ่นฐาน
การดำเนินการย้ายนี้คือ 8 ไบต์
380 0: r_addend = 0
ในอันดับนี้เราใส่ไว้ในก้นของเราว่าที่อยู่ใหม่จะเป็น: S + A \u003d .data + 0 i ในอันดับนี้ อันดับแรกในการกระจายข้อมูล
ตารางชื่อโปรแกรม
ปรากฏน้อยลงในไฟล์ที่ได้รับชัยชนะ
ขึ้นอยู่กับหน่วยความจำเสมือนของกระบวนการในการลบข้อมูลเกี่ยวกับสิ่งเหล่านั้น เช่น ไฟล์ที่กำลังดูอยู่
ไฟล์ที่เชื่อมโยงถูกสร้างขึ้นโดยไฟล์ตัวเชื่อมโยงวัตถุ งานหลักในฐานะตัวเชื่อมโยง viconous:
กำหนดวิธีการแบ่งวัตถุเพื่อดูว่าส่วนใดของไฟล์ที่เลือก
ด้วย Binutils จำเป็นต้องวิเคราะห์สคริปต์ตัวเชื่อมโยงและทำงานกับความหมายของค่าเริ่มต้น
คุณสามารถเลือกสคริปต์ตัวเชื่อมโยงที่ผสานกับ ld --verbose และติดตั้งด้วย ld -T
vikonuvat remіshchennyaข้อความrasdіla มันคุ้มค่าที่จะวางตามลำดับเช่นกิ่งก้านของrozdіlіvrozmіshchuyusyaในหน่วยความจำ
readelf -l hello_world.out ใช่:
Elf file type is EXEC (Executable file) Entry point 0x4000b0 There are 2 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000000000d7 0x00000000000000d7 R E 200000 LOAD 0x00000000000000d8 0x00000000006000d8 0x00000000006000d8 0x000000000000000d 0x000000000000000d RW 200000 Section ไปยังการแมปเซกเมนต์: เซ็กเมนต์ ส่วน... 00 .text 01 .data
ส่วนหัวของ ELF e_phoff , e_phnum และ e_phentsize บอกเราว่ามี 2 ส่วนหัวของโปรแกรมที่เริ่มต้นที่ 0x40 และมากถึง 0x38 ไบต์ของสกิน ดังนั้นกลิ่นเหม็น:
00000040 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 |................| 00000050 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 |[ป้องกันอีเมล]@..... | 00000060 d7 00 00 00 00 00 00 00 d7 00 00 00 00 00 00 00 |................| 00000070 00 00 20 00 00 00 00 00 |.. ..... |
00000070 01 00 00 00 06 00 00 00 | ........| 00000080 d8 00 00 00 00 00 00 00 d8 00 60 00 00 00 00 00 |.............`.....| 00000090 d8 00 60 00 00 00 00 00 0d 00 00 00 00 00 00 00 |..`.............| 000000a0 0d 00 00 00 00 00 00 00 00 20 00 00 00 00 00 |............. | โครงสร้าง typedef ( Elf64_Word p_type; Elf64_Word p_flags; Elf64_Off p_offset; Elf64_Addr p_vaddr; Elf64_Addr p_paddr; Elf64_Xword p_filesz; Elf64_Xword p_memsz; Elf64_X
ลองครั้งแรก:
- 40 0: p_type = 01 00 00 00 = PT_LOAD: สิ่งที่ต้องทำ ฉันคิดว่า tse หมายความว่าคุณจะสนใจปริศนา ประเภทอื่นสามารถเป็นได้ แต่ไม่ใช่ obov'yazkovo buti
- 40 4: p_flags = 05 00 00 00 = อ่านและอ่านได้ ไม่ต้องเขียน TODO
- 40 8: p_offset = 8x 00 สิ่งที่ต้องทำ: อะไร ดูเหมือนว่า usunennya บนซังของกลุ่ม ส่วนที่พันกันหมายความว่าอย่างไร คุณสามารถเล่นกับมันได้: gcc -Wl,-Ttext-segment=0x400030 hello_world.c
- 50 0: p_vaddr = 00 00 40 00 00 00 00 00: ที่อยู่เมลหน่วยความจำเสมือนสำหรับเซ็กเมนต์ที่ถูกครอบครองใน
- 50 8: p_paddr = 00 00 40 00 00 00 00 00: ที่อยู่ทางกายภาพเริ่มต้นที่จะบันทึกในหน่วยความจำ พลังงานสำหรับระบบเท่านั้น ซึ่งโปรแกรมสามารถตั้งค่าที่อยู่จริงได้ ในทางที่แตกต่างกัน เช่นในระบบ System V ก็อาจจะเป็นเช่นนั้น ดูเหมือนว่า NASM เพียงแค่คัดลอก p_vadrr
- 60 0: p_filesz = d7 00 00 00 00 00 00 00: สิ่งที่ต้องทำ vs p_memsz
- 60 8: p_memsz = d7 00 00 00 00 00 00 00: สิ่งที่ต้องทำ
- 70 0: p_align = 00 00 20 00 00 00 00 00: 0 หรือ 1 หมายความว่าไม่จำเป็นต้องจัดตำแหน่ง TODO หมายความว่าอย่างไร ในแบบที่แตกต่างเหนือโลกกับสนามอื่นๆ
อีกอันก็คล้ายๆ
การแมปส่วนไปยังส่วน:
ให้ผู้อ่านบอกเราว่า:
- 0-segment.ข้อความ Aha ที่ชนะและไม่สามารถเขียนได้
- 1-segment.data.
ไฟล์การแปลงเป็นรูปแบบ ELF ประกอบด้วยส่วนต่อไปนี้:
1. ส่วนหัว (ส่วนหัวของเอลฟ์)
ดึงข้อมูลทั่วไปเกี่ยวกับไฟล์และลักษณะสำคัญ2. ตารางส่วนหัวของโปรแกรม
ตาราง Tse ของส่วนที่เกี่ยวข้องกับส่วนไฟล์ของหน่วยความจำแสดงการจับภาพเป็นพื้นที่ของหน่วยความจำในการเขียนส่วนสกิน3. ส่วน
ส่วนสำหรับลบข้อมูลทั้งหมดออกจากไฟล์ (โปรแกรม ข้อมูล ข้อมูลภาษี ฯลฯ)ส่วนสกินอาจพิมพ์ ชื่อ และพารามิเตอร์อื่นๆ ในส่วน ".text" เลือกรหัส ใน ".symtab" - ตารางสัญลักษณ์ของโปรแกรม (ชื่อไฟล์ ขั้นตอน และการเปลี่ยนแปลง) ใน ".strtab" - ตารางแถว ในส่วนที่มี คำนำหน้า ".debug_" - ข้อมูลการปรับแต่ง ฯลฯ .d. .d. นอกจากนี้ ไฟล์ยังมีส่วนว่างที่มีดัชนี 0
4. ตารางส่วนหัวของส่วน
นี่คือตารางสำหรับแทนที่อาร์เรย์ของส่วนหัวของส่วนรูปแบบรายงานได้รับการตรวจสอบโดย ELF Creation
จุดชมวิว DWARF
DWARF เป็นรูปแบบมาตรฐานสำหรับข้อมูลที่ปรับแต่งได้ สามารถดาวน์โหลดมาตรฐานได้จากเว็บไซต์อย่างเป็นทางการ มีการดูรูปแบบสั้น ๆ ที่ยอดเยี่ยม: บทนำสู่รูปแบบการดีบัก DWARF (Michael J. Eager)ต้องการข้อมูลภาษีเพิ่มเติม? วอห์นอนุญาต:
- ติดตั้งเบรกพอยต์ไม่ได้อยู่ในที่อยู่จริง แต่ในหมายเลขแถวของรหัสเอาต์พุตไฟล์ของชื่อฟังก์ชัน
- แสดงและเปลี่ยนค่าของการเปลี่ยนแปลงส่วนกลางและท้องถิ่นตลอดจนพารามิเตอร์ของฟังก์ชัน
- แสดงสแต็กของ Wiki (ย้อนรอย)
- เพื่อแปลงโปรแกรม pokrokovo ไม่ใช่สำหรับคำสั่งแอสเซมเบลอร์เดียว แต่สำหรับแถวของรหัสเอาต์พุต
โหนดแบ่งออกเป็นสองประเภทหลัก: โหนดที่อธิบายข้อมูลและโหนดที่อธิบายรหัส
Woozley เพื่ออธิบายข้อมูล:
- ข้อมูล Tipi:
- ประเภทฐานของข้อมูล (wuzole ที่มีประเภท DW_TAG_base_type) เช่น ประเภท int C
- ประเภทของข้อมูลคลังสินค้า (ฝักบัว)
- มาซิวิ
- โครงสร้าง คลาส การเชื่อมโยง อินเทอร์เฟซ
- วัตถุข้อมูล:
- ค่าคงที่
- พารามิเตอร์ของฟังก์ชัน
- เปลี่ยน
- และอื่น ๆ.
Woozley เพื่ออธิบายรหัส:
- ขั้นตอน (ฟังก์ชัน) – โหนดที่มีแท็ก DW_TAG_subprogram โหนดบนกระดานสามารถแทนที่คำอธิบายของการเปลี่ยนแปลง - พารามิเตอร์ในฟังก์ชันและการเปลี่ยนแปลงในฟังก์ชันในเครื่อง
- หน่วยรวบรวม. ดึงข้อมูลของโปรแกรมและแก้ไขปัญหากับพ่อ
ข้อมูลมากกว่านี้:
- ข้อมูลเกี่ยวกับหมายเลขบรรทัด (ส่วน ".debug_line")
- ข้อมูลเกี่ยวกับมาโคร (ส่วน ".debug_macinfo")
- ข้อมูลเฟรมการโทร (ส่วน ".debug_frame")
การสร้างเอลฟ์
เราจะใช้ความช่วยเหลือของไลบรารี libelf จากแพ็คเกจ elfutils เพื่อสร้างไฟล์ในรูปแบบ EFL Merezha มีบทความดีๆ เกี่ยวกับ libelf - LibELF by Example (น่าเสียดายที่คำอธิบายเกี่ยวกับการสร้างไฟล์ในนั้นสั้น ๆ เท่านั้น) รวมถึงเอกสารประกอบการสร้างไฟล์ประกอบด้วยหลายขั้นตอน:
- การเริ่มต้นการหมิ่นประมาท
- การสร้างส่วนหัวของไฟล์ (ส่วนหัวของ ELF)
- การสร้างตารางส่วนหัวของโปรแกรม
- การสร้างส่วน
- เขียนลงไฟล์
การเริ่มต้นการหมิ่นประมาท
คุณจะต้องเรียกใช้ฟังก์ชัน elf_version (EV_CURRENT) เป็นครั้งคราวและสลับผลลัพธ์ Yakshto vіndіvnyuє EV_NONE - vinikla ให้อภัยที่ไม่สามารถทำงานdiїต่อไปได้ จากนั้นเราต้องสร้างไฟล์ที่ต้องการบนดิสก์ ใช้ที่จับแล้วส่งต่อไปยังฟังก์ชัน elf_begin:เอลฟ์*elf_begin(int fd, Elf_Cmd cmd, Elf*elf)
- fd - ตัวอธิบายไฟล์
- cmd - mode (ELF_C_READ สำหรับการอ่านข้อมูล, ELF_C_WRITE สำหรับการเขียน หรือ ELF_C_RDWR สำหรับการอ่าน/เขียน), vin เกิดจากโหมดของไฟล์ที่กำลังเปิด (ELF_C_WRITE ในโหมดของเรา)
- เอลฟ์ - จำเป็นสำหรับโรบ็อตที่มีไฟล์เก็บถาวร (.a) เท่านั้น เครื่องมือเลือกของเราต้องผ่าน 0
การสร้างส่วนหัว
ส่วนหัวของไฟล์ใหม่ถูกสร้างขึ้นโดยฟังก์ชัน elf32_newehdr:Elf32_Ehdr*elf32_newehdr(เอลฟ์*เอลฟ์);
- elf - ที่จับหมุนโดยฟังก์ชัน elf_begin
#define EI_NIDENT 16 typedef struct ( unsigned char e_ident; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; Elf32_Off e_phoff; Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx; ) Elf32_Ehdr;
ฟิลด์Deyakіїїzapovnenіอันดับมาตรฐาน deyakіจำเป็นต้องกรอกเรา:
- e_ident - อาร์เรย์ของการระบุตัวตนซึ่งอาจมีดัชนีดังกล่าว:
- EI_MAG0, EI_MAG1, EI_MAG2, EI_MAG3 - สัญลักษณ์ผิดพลาด 4 ไบต์ 0x7f, "ELF" ซึ่งฟังก์ชัน elf32_newehdr ทำเพื่อเราแล้ว
- EI_DATA - ระบุประเภทของการเข้ารหัสข้อมูลสำหรับไฟล์: ELFDATA2LSB หรือ ELFDATA2MSB คุณต้องตั้งค่า ELFDATA2LSB ดังนี้: e_ident = ELFDATA2LSB
- EI_VERSION - เวอร์ชันส่วนหัวของไฟล์ที่ติดตั้งให้เราแล้ว
- EI_PAD - ไม่ชิป
- e_type - ประเภทไฟล์สามารถเป็นได้ ET_NONE - ไม่มีประเภท ET_REL - ไฟล์ที่จะย้าย ET_EXEC - การรวมไฟล์ ET_DYN - การแยกไฟล์วัตถุ เป็นต้น เราต้องตั้งค่าประเภทไฟล์เป็น ET_EXEC
- e_machine - สถาปัตยกรรมที่จำเป็นสำหรับไฟล์นี้ เช่น EM_386 - สำหรับสถาปัตยกรรม Intel สำหรับ ARM เราต้องเขียนที่นี่ EM_ARM (40) - div ELF สำหรับสถาปัตยกรรม ARM
- e_version - เวอร์ชันของไฟล์ จำเป็นต้องติดตั้งภาษาใหม่ใน EV_CURRENT
- e_entry - ที่อยู่จุดเริ่มต้นไม่ผูกมัดกับเรา
- e_phoff - การใช้ส่วนหัวของโปรแกรมในไฟล์ e_shoff - การใช้ส่วนหัวของส่วน ไม่สามารถกู้คืนได้
- e_flags - เฉพาะสำหรับโปรเซสเซอร์ prapori สำหรับสถาปัตยกรรมของเรา (Cortex-M3) จำเป็นต้องตั้งค่าเท่ากับ 0x05000000 (ABI เวอร์ชัน 5)
- e_ehsize, e_phentsize, e_phnum, e_sentsize, e_shnum - ไม่ฉลาด
- e_shstrndx - ซ่อนหมายเลขส่วนที่แถวตารางของส่วนหัวของส่วนตั้งอยู่ เรายังไม่มีส่วนที่เหมือนกันเหลือ เราจะใส่จำนวนทั้งหมดในภายหลัง
การสร้างส่วนหัวของโปรแกรม
อย่างที่เคยเกิดขึ้นก่อนหน้านี้ ตารางส่วนหัวของโปรแกรมคือตารางความถูกต้องของส่วนไปยังส่วนไฟล์ของหน่วยความจำ ดังนั้นฉันจึงอยากทราบว่าควรเขียนส่วนสกินไว้ที่ใด ส่วนหัวถูกสร้างขึ้นหลังฟังก์ชันวิธีใช้ elf32_newphdr:Elf32_Phdr * elf32_newphdr(เอลฟ์ * เอลฟ์ นับ size_t);
- เอลฟ์คือมือของเรา
- นับ - จำนวนองค์ประกอบที่สร้างขึ้นในตาราง เนื่องจากเราจะมีเพียงหนึ่งส่วน (พร้อมรหัสโปรแกรม) ดังนั้นการนับจะเท่ากับ 1
องค์ประกอบสกินของตารางส่วนหัวอธิบายโดยโครงสร้างต่อไปนี้:
โครงสร้าง typedef ( Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Word p_filesz; Elf32_Word p_memsz; Elf32_Word p_flags; Elf32_W;
- p_type - ประเภทของกลุ่ม (ส่วน) ที่นี่เรามีหน้าที่รับผิดชอบในการระบุ PT_LOAD - ส่วนที่จะได้รับ
- p_offset - การชดเชยไฟล์, zvіdki pochinaєtsya, จามรี zavantazhuvatemeetsya ในปริศนา เรามี section.text เพื่อให้คุณทราบจำนวนส่วนหัวของไฟล์และส่วนหัวของโปรแกรม เราสามารถคำนวณผลรวมของส่วนหัวทั้งหมดเหล่านี้ได้ นานๆทีจะเอาแบบไหนก็ได้สำหรับฟังก์ชั่นช่วยเหลือ elf32_fsize:
size_t elf32_fsize (ประเภท Elf_Type, จำนวน size_t, รุ่น int ที่ไม่ได้ลงนาม); พิมพ์ - ค่าคงที่ ELF_T_ххх ที่นี่เราจะต้องขยาย ELF_T_EHDR และ ELF_T_PHDR นับ - จำนวนองค์ประกอบของประเภทที่ต้องการ เวอร์ชัน - เลือกตั้งค่าเป็น EV_CURRENT - p_vaddr, p_paddr - ที่อยู่จริงเสมือนซึ่งจะถูกครอบครองในส่วนเดียวกัน เนื่องจากเราไม่มีที่อยู่เสมือน เราจะติดตั้งให้เท่ากับที่อยู่จริงด้วยวิธีที่ง่ายที่สุด - 0 เพื่อให้โปรแกรมของเราสามารถใช้ประโยชน์จากที่อยู่นั้นได้
- p_filesz, p_memsz - การขยายส่วนสำหรับไฟล์และหน่วยความจำ เรามีกลิ่นเหม็นเหมือนกัน แต่ยังไม่มีส่วนของรหัสโปรแกรมเราจะติดตั้งในภายหลัง
- p_flags - เปิดใช้งานสำหรับส่วนหน่วยความจำส่วนตัว สามารถเป็น PF_R - อ่าน, PF_W - เขียน, PF_X - ดูชุดค่าผสมใดก็ได้ ตั้งค่า p_flags เท่ากับ PF_R + PF_X
- p_align - การจัดตำแหน่งกลุ่ม เรามี 4
การสร้างส่วน
หลังจากสร้างหัวเรื่องแล้ว สามารถเปิดส่วนต่างๆ ได้ ส่วนว่างถูกสร้างขึ้นสำหรับฟังก์ชันเพิ่มเติม elf_newscn:Elf_Scn*elf_newscn(เอลฟ์*เอลฟ์);
- elf – แฮนเดิล หมุนก่อนหน้านี้โดยฟังก์ชัน elf_begin
หลังจากสร้างส่วนแล้ว จำเป็นต้องจำชื่อเรื่องของส่วนและสร้างคำอธิบายของส่วนเหล่านี้
เราสามารถดูที่ส่วนหัวของส่วนสำหรับฟังก์ชันเพิ่มเติม elf32_getshdr:
Elf32_Shdr * elf32_getshdr (เอลฟ์_Scn * scn);
- scn - ตัวบ่งชี้ส่วนที่เรานำมาจากฟังก์ชัน elf_newscn
โครงสร้าง typedef ( Elf32_Word sh_name; Elf32_Word sh_type; Elf32_Word sh_flags; Elf32_Addr sh_addr; Elf32_Off sh_offset; Elf32_Word sh_size; Elf32_Word sh_link; Elf3__d_sh;
- sh_name - ชื่อส่วน - ใช้สำหรับส่วนหัวของตารางแถว (section.shstrtab) - div "ตารางแถว"
- sh_type - พิมพ์แทนที่ส่วนสำหรับส่วนที่มีรหัสโปรแกรมจำเป็นต้องตั้งค่า SHT_PROGBITS สำหรับส่วนที่มีตารางแถว - SHT_STRTAB สำหรับตารางสัญลักษณ์ - SHT_SYMTAB
- sh_flags - ธงของส่วนที่สามารถรวมกันได้และเราต้องการเพียงสามอย่าง:
- SHF_ALLOC - หมายความว่าส่วนนี้สนใจปริศนา
- SHF_EXECINSTR - ส่วนที่จะตอบโต้รหัสที่ชนะ
- SHF_STRINGS - ส่วนที่จะกวาดแถวตาราง
- sh_addr - ที่อยู่สำหรับส่วนที่จะหลงเสน่ห์ปริศนา
- sh_offset - ใช้ไฟล์ส่วน - อย่าโกง ติดตั้งห้องสมุดให้เรา
- sh_size - ขนาดส่วน - ไม่ใช่chіpaєmo
- sh_link - รับจำนวนของส่วนที่เชื่อมโยงซึ่งจำเป็นสำหรับการเชื่อมโยงส่วนกับตารางแถวที่คล้ายกัน (ระยะทาง div.)
- sh_info - ข้อมูลเพิ่มเติม วิธีฝากตามประเภทส่วน ตั้งค่าเป็น 0
- sh_addralign - การจัดตำแหน่งที่อยู่ ไม่สามารถอ่านได้
- sh_entsize - วิธีการซ้อนส่วนจากองค์ประกอบจำนวนหนึ่งที่มีค่าเท่ากัน โดยระบุค่าขององค์ประกอบดังกล่าว ไม่ใช่chіpaєmo
Elf_Data * elf_newdata (เอลฟ์_Scn * scn);
- scn - เลือกลบตัวบ่งชี้สำหรับส่วนใหม่
โครงสร้าง typedef ( void * d_buf; Elf_Type d_type; size_t d_size; off_t d_off; size_t d_align; d_version ที่ไม่ได้ลงชื่อ; ) Elf_Data;
- d_buf - ตัวบ่งชี้ข้อมูลดังนั้นจึงจำเป็นต้องเขียนลงในส่วนนี้
- d_type - ประเภทของข้อมูล เราจำเป็นต้องรู้ ELF_T_BYTE
- d_size - ขนาดข้อมูล
- d_off - ใช้ในส่วน ตั้งค่าเป็น 0
- d_align - การจัดตำแหน่ง สามารถตั้งค่าเป็น 1 - ไม่มีการจัดตำแหน่ง
- d_version - เวอร์ชัน ภาษาที่ตั้งค่าสำหรับ EV_CURRENT
ส่วนพิเศษ
เพื่อจุดประสงค์ของเรา เราจะต้องสร้างชุดของส่วนที่จำเป็นขั้นต่ำ:- .text - ส่วนที่มีรหัสโปรแกรม
- .symtab - ตารางสัญลักษณ์ในไฟล์
- .strtab - ตารางของแถวสำหรับลบชื่อสัญลักษณ์ออกจากส่วน .symtab ส่วนย่อยในส่วนที่เหลือไม่ใช่ชื่อตัวเอง แต่เป็นดัชนี
- .shstrtab - ตารางของแถวเพื่อลบชื่อส่วน
ส่วน.
ส่วนนี้เป็นการลบโค้ดที่กำลังเช็คเอาท์ ดังนั้นคุณต้องตั้งค่า sh_type เป็น SHT_PROGBITS, sh_flags - เป็น SHF_EXECINSTR + SHF_ALLOC, sh_addr - ตั้งค่าเป็นที่อยู่เดียวกัน ซึ่งโค้ดทั้งหมดจะถูกดักจับส่วน.
ส่วนค้นหาคำอธิบายสัญลักษณ์ (ฟังก์ชัน) ของโปรแกรมและไฟล์ซึ่งได้อธิบายถึงกลิ่นเหม็น ประกอบด้วยองค์ประกอบต่อไปนี้ของส่วนหัว แต่ละรายการมี 16 ไบต์:โครงสร้าง typedef ( Elf32_Word st_name; Elf32_Addr st_value; Elf32_Word st_size; unsigned char st_info; unsigned char st_other; Elf32_Half st_shndx; ) Elf32_Sym;
- st_name - ชื่ออักขระ (ดัชนีตารางแถว strtab)
- st_value - ค่า (ที่อยู่อินพุตสำหรับฟังก์ชันหรือ 0 สำหรับไฟล์) เศษ Cortex-M3 สามารถใช้ระบบคำสั่ง Thumb-2 ในขณะที่ที่อยู่ของภาษาสามารถยกเลิกการจับคู่ได้ (ที่อยู่จริง + 1)
- st_size - ความยาวของโค้ดฟังก์ชัน (0 สำหรับไฟล์)
- st_info - ประเภทสัญลักษณ์และขอบเขต หากต้องการกำหนดค่าของฟิลด์ ให้ใช้แมโคร
#กำหนด ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
โดยที่ b คือขอบเขต และ t คือประเภทอักขระ
ขอบเขตสามารถเป็น STB_LOCAL (สัญลักษณ์ไม่ปรากฏในไฟล์วัตถุอื่น) หรือ STB_GLOBAL (มองเห็นได้) เพื่อความง่าย เราใช้ STB_GLOBAL
ประเภทสัญลักษณ์ - STT_FUNC สำหรับฟังก์ชัน STT_FILE สำหรับไฟล์ - st_other - ตั้งค่าเป็น 0
- st_shndx – ดัชนีส่วน ซึ่งกำหนดสัญลักษณ์ (ส่วน index.text) หรือ SHN_ABS สำหรับไฟล์
ดัชนีส่วนที่อยู่เบื้องหลังคำอธิบาย її scn สามารถกำหนดให้กับตัวช่วย elf_ndxscn:
size_t elf_ndxscn(เอลฟ์_Scn *scn);
ส่วนนี้สร้างด้วยอันดับ เฉพาะ sh_type เท่านั้นที่ควรตั้งค่าเป็น SHT_SYMTAB และส่วน index.strtab ควรเขียนในฟิลด์ sh_link ด้วยอันดับดังกล่าว ts_sections จะเกี่ยวข้องกัน
ส่วน.
ส่วนนี้จะลบชื่อของสัญลักษณ์ทั้งหมดออกจาก section.symtab สร้างเป็นส่วนปกติ แต่จำเป็นต้องตั้งค่า sh_type เป็น SHT_STRTAB, sh_flags เป็น SHF_STRINGS ดังนั้นส่วนนี้จึงกลายเป็นตารางแถวสามารถเลือกข้อมูลสำหรับส่วนได้เมื่อผ่านอาร์เรย์ข้อความเอาต์พุต ซึ่งเป็นตัวบ่งชี้ที่เราสามารถเขียนในคำอธิบายของส่วนข้อมูล (d_buf)
ส่วน.
ส่วน - ตารางของแถวเพื่อแทนที่ส่วนหัวของทุกส่วนของไฟล์รวมถึงส่วนหัวของตัวเอง สร้างเช่นนี้ section.strtab หลังจากสร้างดัชนีแล้วจำเป็นต้องเขียนในฟิลด์ e_shstrndx ของส่วนหัวของไฟล์ตารางแถว
แถวของตารางที่จะแทนที่แถวที่อยู่ในแถวจะลงท้ายด้วยศูนย์ไบต์ ไบต์แรกในตารางนี้คือ 0 เช่นกัน ดัชนีแถวในตารางเป็นเพียงการเลื่อนเป็นไบต์บน cob ของตารางตามลำดับนี้ แถวแรก "ชื่อ" อาจเป็นดัชนี 1 แถวรุก "var" อาจเป็นดัชนี 6ดัชนี 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \0 n am e \0 v a r \0
เขียนลงไฟล์
นอกจากนี้ส่วนหัวของส่วนนั้นได้ถูกสร้างขึ้นแล้วตอนนี้คุณต้องเขียนลงในไฟล์และทำงานให้เสร็จด้วยการหมิ่นประมาท การบันทึกฟังก์ชัน elf_update:off_t elf_update (เอลฟ์ * เอลฟ์, Elf_Cmd cmd);
- เอลฟ์ - จัดการ
- cmd - คำสั่งที่ดีสำหรับการเขียน ELF_C_WRITE
เราทำงานให้เสร็จด้วยไลบรารีฟังก์ชัน elf_end ซึ่งผ่านตัวอธิบายของเรา มากเกินไปที่จะปิดไฟล์ก่อนหน้านี้
อย่างไรก็ตาม การสร้างไฟล์ไม่ได้เป็นการตอบโต้ข้อมูลส่วนรวม เนื่องจากเราเพิ่มข้อมูลนั้นลงในการแจกจ่ายที่ไม่เหมาะสม
การสร้าง DWARF
การรวบรวมข้อมูลที่คล้ายกันสำหรับไลบรารีเพิ่มเติม ซึ่งรวมอยู่ในไฟล์ pdf พร้อมเอกสาร (libdwarf2p.1.pdf - อินเทอร์เฟซไลบรารีของผู้ผลิตไปยัง DWARF)การสร้างข้อมูลภาษีประกอบด้วยขั้นตอนต่อไปนี้:
- การสร้างVuzlіv (DIE - การดีบักรายการข้อมูล)
- การสร้างคุณลักษณะของมหาวิทยาลัย
- การสร้างประเภทข้อมูล
- การสร้างขั้นตอน (ฟังก์ชัน)
การเริ่มต้นผู้ผลิต libdwarf
เราจะสร้างข้อมูลภาษีในเวลาที่รวบรวมพร้อมกับการสร้างสัญลักษณ์ในส่วนสำหรับการเริ่มต้น เราจะชนะฟังก์ชัน dwarf_producer_init_c ไลบรารีมีฟังก์ชันการเริ่มต้นเพิ่มเติมอีกเล็กน้อย (dwarf_producer_init, dwarf_producer_init_b) ซึ่งขึ้นอยู่กับลักษณะบางอย่างที่อธิบายไว้ในเอกสารประกอบ ตามหลักการแล้ว คุณสามารถเอาชนะพวกมันได้
Dwarf_P_Debug dwarf_producer_init_c (Dwarf_Unsigned flag, Dwarf_Callback_Func_c func, Dwarf_Handler errhand, Dwarf_Ptr errarg, void *user_data, Dwarf_Error *ข้อผิดพลาด)
- แฟล็ก - การรวมกันของ "หรือ" ของค่าคงที่จำนวนหนึ่งเพื่อกำหนดพารามิเตอร์ต่างๆ ตัวอย่างเช่น ขนาดของข้อมูล ลำดับของไบต์ (little-endian, big-endian) รูปแบบการย้ายตำแหน่ง ภาษาที่เราต้องการ DW_DLC_WRITE และ DW_DLC_SYMBOLIC_RELOCATIONS
- func - ฟังก์ชันการโทรกลับ ซึ่งจะถูกเรียกใช้เมื่อยุบส่วน ELF ด้วยข้อมูลที่กำหนดเอง ส่วนรายงาน ที่สาขา "การสร้างส่วนที่มีข้อมูลภาษี"
- errhand - ตัวบ่งชี้สำหรับฟังก์ชั่นราวกับว่าคุณจะโทรออกเมื่อคุณได้รับอภัยโทษ ผ่านได้ 0
- errarg - ข้อมูลที่จะส่งผ่านไปยังฟังก์ชัน errhand สามารถตั้งค่าเป็น 0
- user_data - ข้อมูลที่จะส่งผ่านไปยังฟังก์ชัน func สามารถตั้งค่าเป็น 0
- ข้อผิดพลาด - รหัสอภัยโทษสิ่งที่ต้องเปลี่ยน
การสร้าง Woozliv (DIE - การดีบักรายการข้อมูล)
ตามที่ได้อธิบายเพิ่มเติม ข้อมูล nalagodzhuvalnaya สร้างโครงสร้างคล้ายต้นไม้ ในการสร้าง vuzol ของต้นไม้นั้น คุณต้อง:- สร้างฟังก์ชัน yogo dwarf_new_die
- เพิ่มแอตทริบิวต์ใหม่
Dwarf_P_Die dwarf_new_die(Dwarf_P_Debug dbg, Dwarf_Tag new_tag, Dwarf_P_Die parent, Dwarf_P_Die child, Dwarf_P_Die left_sibling, Dwarf_P_Die right_sibling, คนแคระ
- new_tag – node tag (type) – ค่าคงที่ DW_TAG_xxxx ซึ่งสามารถพบได้ในไฟล์ libdwarf.h
- ผู้ปกครอง, ลูก, พี่น้องซ้าย, พี่น้องขวา - พ่อที่ดี, เหยื่อ, สิงโตและขวา sus_di vuzla ไม่จำเป็นต้องระบุพารามิเตอร์ทั้งหมดก็เพียงพอแล้วที่จะระบุพารามิเตอร์ให้ตั้งค่า 0 แทนพารามิเตอร์อื่น
- ข้อผิดพลาด - แก้ไขรหัสของการให้อภัยเมื่อїїviniknіnі
การสร้างคุณลักษณะของมหาวิทยาลัย
สำหรับการสร้างแอตทริบิวต์ของโหนด ค่านี้เป็นโฮมของฟังก์ชัน บางครั้งการระบุว่าฟังก์ชันใดจำเป็นในการสร้างแอตทริบิวต์ที่จำเป็นนั้นเป็นปัญหา ดังนั้นฉันจึงพบว่ามีการขุดคุ้ยที่เอาต์พุตโค้ดของไลบรารีอยู่สองสามครั้ง การกระทำที่มีหน้าที่จะอธิบายไว้ที่นี่ การกระทำด้านล่าง - ในหน่วยงานที่เกี่ยวข้อง กลิ่นเหม็นทั้งหมดยอมรับพารามิเตอร์ Ownerdie - คำอธิบายของโหนดที่จะเพิ่มแอตทริบิวต์ และเปลี่ยนรหัสให้อภัยในพารามิเตอร์ข้อผิดพลาดฟังก์ชัน dwarf_add_AT_name เพิ่มแอตทริบิวต์ "im'ya" (DW_AT_name) ไปยังไซต์ โหนดส่วนใหญ่อาจมีชื่อ (เช่น โพรซีเดอร์ การเปลี่ยนแปลง ค่าคงที่) บางชื่ออาจมีหรือไม่มีชื่อก็ได้ (เช่น Compilation Unit)
Dwarf_P_Attribute dwarf_add_AT_name (เจ้าของ Dwarf_P_Die, ถ่าน * ชื่อ, Dwarf_Error * ข้อผิดพลาด)
- ชื่อ - ค่าของแอตทริบิวต์ (ชื่อของโหนด)
ฟังก์ชัน dwarf_add_AT_signed_const, dwarf_add_AT_unsigned_const เพิ่มแอตทริบิวต์ของค่าที่ลงนาม (ไม่ได้ลงนาม) ไปยังโหนดคำสั่ง แอตทริบิวต์ที่ลงนามและไม่ได้ลงนามถูกเลือกสำหรับการตั้งค่าของค่าคงที่, rozmіrіv, ตัวเลขในแถว, จากนั้น รูปแบบฟังก์ชัน:
Dwarf_P_Attribute dwarf_add_AT_(un)signed_const(Dwarf_P_Debug dbg, เจ้าของ Dwarf_P_Die, Dwarf_Half attr, ค่า Dwarf_Signed, Dwarf_Error *ข้อผิดพลาด)
- dbg – Dwarf_P_Debug descriptor ซึ่งถูกลบออกในระหว่างการเริ่มต้นไลบรารี
- attr - แอตทริบิวต์ค่าที่ตั้งไว้ - ค่าคงที่ DW_AT_xxxx ซึ่งสามารถพบได้ในไฟล์ libdwarf.h
- ค่า - ค่าแอตทริบิวต์
หน่วยรวบรวม
ต้นไม้สามารถมีรากได้หรือไม่ - เรามีการรวบรวมเพียงรายการเดียว เพื่อให้เราสามารถค้นหาข้อมูลเกี่ยวกับโปรแกรม (ตัวอย่างเช่น ชื่อของไฟล์ส่วนหัว การเขียนโปรแกรม mov สิ่งที่เขียน ชื่อของคอมไพเลอร์ ความไวของสัญลักษณ์ (การเปลี่ยนแปลง, ฟังก์ชัน) ของฟังก์ชัน, โปรแกรมการลงทะเบียนส่วนหัว, ที่อยู่อีเมล ฯลฯ) โดยหลักการแล้ว คุณลักษณะประจำวันคือ obov'yazkovimi ตัวอย่างเช่น ลองสร้างข้อมูลเกี่ยวกับไฟล์หลักและคอมไพเลอร์ข้อมูลเกี่ยวกับไฟล์ส่วนหัว
เพื่อบันทึกข้อมูลเกี่ยวกับไฟล์ส่วนหัว เลือกแอตทริบิวต์ "ชื่อ" (DW_AT_name) ปิดใช้งานฟังก์ชัน dwarf_add_AT_name ดังแสดงในส่วน "การสร้างแอตทริบิวต์โหนด"ข้อมูลเกี่ยวกับคอมไพเลอร์
ฟังก์ชันชัยชนะ dwarf_add_AT_producer:Dwarf_P_Attribute dwarf_add_AT_name (เจ้าของ Dwarf_P_Die, ถ่าน *producer_string, Dwarf_Error *ข้อผิดพลาด)
- Producer_string - แถวของข้อมูลข้อความ
สร้างรายการข้อมูลทั่วไป
โทรเมื่อเรียกใช้ฟังก์ชัน (โปรแกรมย่อย) และวางพารามิเตอร์ของที่อยู่ของเทิร์นไว้บนสแต็ก (หากคอมไพเลอร์สามารถทำงานได้ในแบบของมันเอง) จะเรียกว่า Call Frame ตัวควบคุมต้องการข้อมูลเกี่ยวกับรูปแบบของเฟรมเพื่อให้กำหนดที่อยู่ของฟังก์ชันส่งคืนได้อย่างถูกต้องและชักนำการย้อนกลับ - การเรียกกลับของฟังก์ชันซึ่งปลูกฝังฟังก์ชันการสตรีมและพารามิเตอร์ของฟังก์ชันเหล่านี้ให้กับเรา นอกจากนี้ยังมีการเรียกรีจิสเตอร์ของโปรเซสเซอร์เนื่องจากบันทึกไว้ในสแต็ก รหัสที่จองพื้นที่บนสแต็กและบันทึกการลงทะเบียนตัวประมวลผลเรียกว่าอารัมภบทของฟังก์ชัน รหัสที่คืนค่าการลงทะเบียนสแต็กเรียกว่าบทส่งท้ายข้อมูลนี้ควรเก็บไว้ในคอมไพเลอร์ ตัวอย่างเช่น อารัมภบทและบทส่งท้ายเป็น neobov'yazkovo เนื่องมาจาก cob และ ตัวอย่างเช่น ฟังก์ชัน; ชนะเฟรม; การลงทะเบียนโปรเซสเซอร์สามารถบันทึกไว้ในการลงทะเบียนอื่น ๆ เป็นต้น
ดังนั้นเจ้าของจำเป็นต้องรู้วิธีเปลี่ยนค่าของการลงทะเบียนโปรเซสเซอร์และ de stink จะถูกบันทึกเมื่อเข้าสู่ขั้นตอน ข้อมูลนี้เรียกว่า Call Frame Information - ข้อมูลเกี่ยวกับรูปแบบเฟรม สำหรับที่อยู่สกินในโปรแกรม (เพื่อล้างโค้ด) มีการระบุที่อยู่ของเฟรมในหน่วยความจำ (Canonical Frame Address - CFA) และข้อมูลเกี่ยวกับการลงทะเบียนของโปรเซสเซอร์ เช่น คุณสามารถระบุได้ว่า:
- การลงทะเบียนไม่ได้นำมาจากขั้นตอน
- รีจิสเตอร์ไม่เปลี่ยนค่าในโพรซีเดอร์
- รีจิสเตอร์จะถูกบันทึกไว้ในสแต็กหลังที่อยู่ CFA+n
- บันทึกการลงทะเบียนในการลงทะเบียนอื่น
- การลงทะเบียนจะถูกบันทึกไว้ในหน่วยความจำสำหรับที่อยู่เฉพาะเนื่องจากสามารถนับได้ด้วยวิธีที่ไม่ชัดเจน
- และอื่น ๆ.
- DW_CFA_set_loc - ชี้ไปที่ที่อยู่ปัจจุบันของโปรแกรม
- DW_CFA_advance_loc - ตัวบ่งชี้ผ่านสำหรับ sprat ของไบต์
- DW_CFA_def_cfa - ระบุที่อยู่ของเฟรมสแต็ก (ค่าคงที่ที่เป็นตัวเลข)
- DW_CFA_def_cfa_register - ระบุที่อยู่ของเฟรมสแต็ก (นำมาจากการลงทะเบียนโปรเซสเซอร์)
- DW_CFA_def_cfa_expression - ระบุวิธีคำนวณที่อยู่ของเฟรมสแต็ก
- DW_CFA_same_value - ระบุว่าไม่มีการเปลี่ยนแปลงการลงทะเบียน
- DW_CFA_register - ระบุการลงทะเบียนที่จะบันทึกในการลงทะเบียนอื่น
- และอื่น ๆ.
คอมไพเลอร์ของฉันสร้างขั้นตอนที่มี CFA ในการลงทะเบียน sp(r13) เราสร้าง CIE สำหรับขั้นตอนทั้งหมด ข้อใดคือฟังก์ชัน dwarf_add_frame_cie:
Dwarf_Unsigned dwarf_add_frame_cie (Dwarf_P_Debug dbg, char *augmenter, Dwarf_Small code_align, Dwarf_Small data_align, Dwarf_Small ret_addr_reg, Dwarf_Ptr init_bytes, Dwarf_Un
- ตัวขยาย - สตริงสำหรับการเข้ารหัส UTF-8 ซึ่งแสดงว่าก่อน CIE หรือ FDE เป็นข้อมูลแพลตฟอร์มเพิ่มเติม เราใส่แถวว่าง
- code_align - การจัดตำแหน่งรหัสเป็นไบต์ (เรามี 2)
- data_align - การจัดตำแหน่งข้อมูลสำหรับเฟรม (ตั้งค่าเป็น -4 ซึ่งหมายความว่าพารามิเตอร์ทั้งหมดใช้ 4 ไบต์ในสแต็กและขยายลงในหน่วยความจำ)
- ret_addr_reg - ลงทะเบียนเพื่อรับที่อยู่ของขั้นตอน (เรามี 14)
- init_bytes - อาร์เรย์สำหรับดึงคำสั่ง DW_CFA_хххх น่าเสียดายที่ไม่มีวิธีการสร้างอาร์เรย์นี้ด้วยตนเอง คุณสามารถสร้างด้วยตนเองหรือดูในไฟล์ elf ไม่ว่าคอมไพเลอร์ใดจะสร้างซึ่งฉันสร้างขึ้น สำหรับรหัสผ่านของฉัน 3 ไบต์: 0x0C, 0x0D, 0 ซึ่งถอดรหัสเช่น DW_CFA_def_cfa: r13 ofs 0
- init_bytes_len - ความยาวของอาร์เรย์ init_bytes
การสร้างประเภทข้อมูล
ก่อนหน้านั้นในการสร้างขั้นตอนสำหรับการเปลี่ยนแปลงนั้นจำเป็นต้องสร้างปมที่ด้านหลังศีรษะซึ่งสอดคล้องกับประเภทของข้อมูล ประเภทของข้อมูลไม่มีตัวตน แต่กลิ่นจะขึ้นอยู่กับประเภทพื้นฐาน (ประเภทพื้นฐานในตาราง int, เพิ่มเป็นสองเท่า) ประเภทอื่นๆ จะขึ้นอยู่กับประเภทพื้นฐานประเภทฐาน - แท็ก wuzol іz DW_TAG_base_type ใหม่สามารถมีแอตทริบิวต์ buti:
- "im'ya" (DW_AT_name)
- "การเข้ารหัส" (DW_AT_encoding) - หมายถึงวิธีที่ข้อมูลอธิบายประเภทฐานที่กำหนด (เช่น DW_ATE_boolean - ตรรกะ DW_ATE_float - จุดลอยตัว DW_ATE_signed - cel ที่เซ็นชื่อ DW_ATE_unsigned - cel ที่ไม่ได้ลงชื่อ ฯลฯ)
- "ขนาด" (DW_AT_byte_size - ขนาดสำหรับไบต์ หรือ DW_AT_bit_size - ขนาดสำหรับบิต)
ตัวอย่างเช่น ในการสร้าง int ประเภทฐานเครื่องหมาย cilium 32 บิต เราจะต้องสร้าง vuzel ด้วยแท็ก DW_TAG_base_type และตั้งค่าแอตทริบิวต์ DW_AT_name - int, DW_AT_encoding - DW_ATE_signed, DW_AT_byte_size - 4
หลังจากสร้างประเภทพื้นฐานแล้ว คุณสามารถสร้างประเภทที่คล้ายกันได้ โหนดดังกล่าวมีหน้าที่รับผิดชอบแอตทริบิวต์ DW_AT_type - ส่งประเภทฐาน ตัวอย่างเช่น ตัวชี้ไปยัง int - vuzol ที่มีแท็ก DW_TAG_pointer_type มีความผิดในการแก้แค้นในแอตทริบิวต์ DW_AT_type ซึ่งถูกกำหนดไว้ในการสร้างประเภท "int" ก่อนหน้านี้
คุณลักษณะจากการร้องขอไปยังโหนดอื่นถูกสร้างขึ้นโดยฟังก์ชัน dwarf_add_AT_reference:
Dwarf_P_Attribute dwarf_add_AT_reference (Dwarf_P_Debug dbg, เจ้าของ Dwarf_P_Die, Dwarf_Half attr, Dwarf_P_Die otherdie, Dwarf_Error *ข้อผิดพลาด)
- attr - แอตทริบิวต์ ครั้ง DW_AT_type
- otherdie - คำอธิบายของโหนดประเภทที่ขอ
รวมขั้นตอนต่างๆ
สำหรับการสร้างขั้นตอน จำเป็นต้องอธิบายข้อมูลภาษีประเภทหนึ่ง - ข้อมูลหมายเลขบรรทัด มันจะทำหน้าที่ในการตั้งค่าคำสั่งสกินแมชชีนเป็นบรรทัดเดียวของรหัสเอาต์พุต และสำหรับความเป็นไปได้ในการปรับแต่งภายหลังบรรทัดของโปรแกรม ข้อมูลนี้รวบรวมจากส่วน .debug_line ถ้าเรามีพื้นที่เล็กพอ มันก็จะถูกบันทึกจากรูปลักษณ์ของเมทริกซ์ หนึ่งแถวสำหรับคำสั่งสกินที่มีคอลัมน์ดังกล่าว:- ชื่อไฟล์พร้อมรหัสทางออก
- หมายเลขแถวของไฟล์ใด
- หมายเลขคอลัมน์ไฟล์
- chi єคำสั่งโดย cob ของตัวดำเนินการ chi ไปยังบล็อกของตัวดำเนินการ
- และอื่น ๆ.
ในระดับต่ำเช่นนี้ การสร้างข้อมูลทำได้ยาก ดังนั้นในไลบรารี libdwarf จึงมีการถ่ายโอนฟังก์ชันบางอย่าง ซึ่งทำให้งานง่ายขึ้น
การบันทึกชื่อไฟล์สำหรับคำแนะนำเกี่ยวกับสกินมีราคาแพง ดังนั้นควรบันทึกชื่อไว้ในตารางพิเศษ ในการสร้างดัชนีไฟล์ จำเป็นต้องแทนที่ฟังก์ชัน dwarf_add_file_decl:
Dwarf_Unsigned dwarf_add_file_decl (Dwarf_P_Debug dbg, char *name, Dwarf_Unsigned dir_idx, Dwarf_Unsigned time_mod, Dwarf_Unsigned length, Dwarf_Error *ข้อผิดพลาด)
- ชื่อ - ชื่อของไฟล์
- dir_idx – ดัชนีของโฟลเดอร์ที่มีไฟล์อยู่ ดัชนีสามารถนำมาจากฟังก์ชันช่วยเหลือ dwarf_add_directory_decl หากคุณต้องการผูกพาธเพิ่มเติม คุณสามารถตั้งค่า 0 เป็นดัชนีโฟลเดอร์และไม่ต้องผูก dwarf_add_directory_decl
- time_mod – ชั่วโมงการแก้ไขไฟล์ ไม่สามารถระบุได้ (0)
- ความยาว - ขยายไฟล์และไม่ผูกมัด (0)
สำหรับการสร้างข้อมูลเกี่ยวกับหมายเลขบรรทัด มีสามฟังก์ชัน: dwarf_add_line_entry_b, dwarf_lne_set_address, dwarf_lne_end_sequence ดังที่เราเห็นด้านล่าง
การสร้างข้อมูลภาษีสำหรับขั้นตอนจะได้รับในตอนท้ายของขั้นตอน:
- สร้างเป็นสัญลักษณ์ขั้นตอนของส่วน
- การสร้างโหนดโพรซีเดอร์ด้วยแอตทริบิวต์
- การสร้างขั้นตอน FDE
- การตั้งค่าพารามิเตอร์ในโพรซีเดอร์
- การรวบรวมข้อมูลเกี่ยวกับหมายเลขแถว
การสร้างสัญลักษณ์ขั้นตอน
สัญลักษณ์ขั้นตอนถูกสร้างขึ้นตามที่อธิบายไว้ในส่วน "Section.symtab" สำหรับพวกเขา สัญลักษณ์ของขั้นตอนจะถูกแทรกด้วยสัญลักษณ์ของไฟล์ที่พวกเขาเปลี่ยนรหัสอินพุตของขั้นตอนเหล่านี้ ฉันสร้างสัญลักษณ์ให้กับไฟล์ก่อน จากนั้นตามด้วยขั้นตอน ซึ่งไฟล์จะแม่นยำยิ่งขึ้น และหากมีการซื้อซ้ำขั้นตอนดังกล่าวจากไฟล์สตรีม ไฟล์นั้นไม่จำเป็นต้องสร้างอีกการสร้างโหนดขั้นตอนด้วยแอตทริบิวต์
ในทางกลับกัน เราสร้างโหนดสำหรับฟังก์ชันเพิ่มเติม dwarf_new_die (ส่วน div. "Creation of Wuzley") โดยระบุเป็นแท็ก DW_TAG_subprogram และเป็นตัวพ่อ - Compilation Unit (ซึ่งเป็นขั้นตอนส่วนกลาง) หรือ DIE (ซึ่ง เป็นของท้องถิ่น) มาสร้างแอตทริบิวต์กัน:- ชื่อโพรซีเดอร์ (ฟังก์ชัน dwarf_add_AT_name, div. "สร้างแอตทริบิวต์ของโหนด")
- หมายเลขแถวของไฟล์ ซึ่งรหัสขั้นตอนเริ่มต้น (แอตทริบิวต์ DW_AT_decl_line) ฟังก์ชัน dwarf_add_AT_unsigned_const (div. "สร้างแอตทริบิวต์ของโหนด")
- ที่อยู่อีเมลของขั้นตอน (แอตทริบิวต์ DW_AT_low_pc), ฟังก์ชัน dwarf_add_AT_targ_address, div
- ที่อยู่สิ้นสุดของขั้นตอน (แอตทริบิวต์ DW_AT_high_pc), ฟังก์ชัน dwarf_add_AT_targ_address, div
- ประเภทของผลลัพธ์ที่เปลี่ยนตามขั้นตอน (แอตทริบิวต์ DW_AT_type - ตั้งค่าก่อนประเภทการสร้าง div "ประเภทข้อมูลที่สร้างขึ้น") เนื่องจากขั้นตอนนี้ไม่ได้หมุนอะไรเลย จึงไม่จำเป็นต้องสร้างแอตทริบิวต์ใดๆ
Dwarf_P_Attribute dwarf_add_AT_targ_address_b (Dwarf_P_Debug dbg, เจ้าของ Dwarf_P_Die, Dwarf_Half attr, Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, Dwarf_Error *ข้อผิดพลาด)
- attr - แอตทริบิวต์ (DW_AT_low_pc หรือ DW_AT_high_pc)
- pc_value - ค่าที่อยู่
- sym_index – ดัชนีของสัญลักษณ์ขั้นตอนในตาราง Neobov'viscous สามารถส่งได้ 0
การสร้างขั้นตอน FDE
ดังที่ได้กล่าวไว้ก่อนหน้านี้ในหัวข้อ "การสร้างรายการข้อมูลทั่วไป" สำหรับขั้นตอนเกี่ยวกับผิวหนัง จำเป็นต้องสร้างคำอธิบายของเฟรม ซึ่งควรใช้ในขั้นตอนคิลกา:- การสร้าง FDE ใหม่ (div. การสร้างรายการข้อมูลทั่วไป)
- นำ FDE ที่สร้างขึ้นไปยังรายการ
- การเพิ่มคำแนะนำให้กับ FDE ที่สร้างขึ้น
Dwarf_P_Fde dwarf_new_fde (Dwarf_P_Debug dbg, Dwarf_Error *ข้อผิดพลาด)
ฟังก์ชันจะเปลี่ยนหมายเลขอ้างอิง FDE ใหม่เป็น DW_DLV_BADADDR ขออภัย
คุณสามารถรับ FDE ใหม่ไปยังรายการโดยใช้ dwarf_add_frame_fde:
Dwarf_Unsigned dwarf_add_frame_fde(Dwarf_P_Debug dbg, Dwarf_P_Fde fde, Dwarf_P_Die die, Dwarf_Unsigned cie, Dwarf_Addr virt_addr, Dwarf_Unsigned code_len, Dwarf_Unsigned sym
- fde - ตัวบ่งชี้ที่เลือก
- ตาย - ขั้นตอน DIE (div. สร้างโหนดขั้นตอนด้วยแอตทริบิวต์)
- cie - ตัวอธิบาย CIE (รายการข้อมูลทั่วไป div.)
- virt_addr - ที่อยู่อีเมลของขั้นตอนของเรา
- code_len - ความยาวขั้นตอนเป็นไบต์
ในกรณีนี้ คุณสามารถเพิ่มคำแนะนำ DW_CFA_хххх ไปยัง FDE ของเราได้ ใช้ฟังก์ชัน dwarf_add_fde_inst และ dwarf_fde_cfa_offset ขั้นแรก เพิ่มคำสั่งที่กำหนดลงในรายการ:
Dwarf_P_Fde dwarf_add_fde_inst (Dwarf_P_Fde fde, Dwarf_Small op, Dwarf_Unsigned val1, Dwarf_Unsigned val2, Dwarf_Error *ข้อผิดพลาด)
- op - รหัสคำสั่ง (DW_CFA_хххх)
- val1, val2 - พารามิเตอร์คำสั่ง (ต่างกันสำหรับคำสั่งสกิน, div. Standard, ส่วน 6.4.2 คำสั่ง Call Frame)
Dwarf_P_Fde dwarf_fde_cfa_offset (Dwarf_P_Fde fde, Dwarf_Unsigned reg, Dwarf_Signed offset, Dwarf_Error *ข้อผิดพลาด)
- fde - จัดการเพื่อสร้าง FDE
- reg - register ซึ่งเขียนลงในเฟรม
- ออฟเซ็ต - ออฟเซ็ตของเฟรม (ไม่ใช่ไบต์ แต่เป็นองค์ประกอบเฟรม div การป้อนข้อมูลทั่วไป data_align)
การสร้างพารามิเตอร์ขั้นตอน
การสร้างพารามิเตอร์ของขั้นตอนนั้นคล้ายกับการสร้างการเปลี่ยนแปลงที่สำคัญที่สุด divs "การสร้างการเปลี่ยนแปลงและค่าคงที่"การสร้างข้อมูลเกี่ยวกับหมายเลขแถว
การสร้างข้อมูลนี้มีดังนี้:- ที่จุดเริ่มต้นของขั้นตอน เราเริ่มบล็อกคำสั่งด้วยฟังก์ชัน dwarf_lne_set_address
- สำหรับรหัสสกินไลน์ (หรือคำสั่งเครื่อง) เราสร้างข้อมูลเกี่ยวกับรหัสออก (dwarf_add_line_entry)
- ตัวอย่างเช่น โพรซีเดอร์สิ้นสุดบล็อกคำสั่งด้วยฟังก์ชัน dwarf_lne_end_sequence
Dwarf_Unsigned dwarf_lne_set_address (Dwarf_P_Debug dbg, Dwarf_Addr off, Dwarf_Unsigned symidx, Dwarf_Error *ข้อผิดพลาด)
- offs - ที่อยู่ของขั้นตอน (ที่อยู่ของคำสั่งเครื่องแรก)
- sym_idx - ดัชนีสัญลักษณ์ (ไม่ผูกมัด คุณสามารถป้อน 0)
ฟังก์ชัน dwarf_add_line_entry_b เพิ่มข้อมูล section.debug_line เกี่ยวกับบรรทัดของโค้ดผลลัพธ์ ฉันเรียกฟังก์ชันนี้สำหรับคำสั่งสกินแมชชีน:
Dwarf_Unsigned dwarf_add_line_entry_b(Dwarf_P_Debug dbg, Dwarf_Unsigned file_index, Dwarf_Addr code_offset, Dwarf_Unsigned lineno, Dwarf_Signed column_number, Dwarf_Bool is_source_stmt_begin, Dwarf_Bool is_basic_block_begin, Dwarf_Bool is_epilogue_begin, Dwarf_Bool is_prologue_end, Dwarf_Unsigned isa, Dwarf_Unsigned discriminator, Dwarf_Error *error)
- file_index - ดัชนีไฟล์ของโค้ดเอาต์พุต ซึ่งก่อนหน้านี้ถูกลบออกโดยฟังก์ชัน dwarf_add_file_decl (div. "ขั้นตอนการสร้าง")
- code_offset - ที่อยู่ของคำสั่งเครื่องเธรด
- lineno - หมายเลขแถวของไฟล์โค้ดเอาต์พุต
- column_number - หมายเลขคอลัมน์ของไฟล์โค้ดเอาต์พุต
- is_source_stmt_begin - คำสั่งบรรทัดที่ 1 ก่อนในโค้ดในแถว lineno (ฉันเริ่ม vicorist 1)
- is_basic_block_begin - คำสั่งบรรทัดที่ 1 ก่อนในกลุ่มคำสั่ง (ฉันต้องเริ่ม 0)
- is_epilogue_begin - คำแนะนำแบบอินไลน์ลำดับที่ 1 ก่อนในบทส่งท้ายของขั้นตอน (ไม่ผูกมัด ฉันมี 0)
- is_prologue_end - คำแนะนำแบบอินไลน์ลำดับที่ 1 เพื่อหยุดที่บทนำของขั้นตอน (obv'yazykovo!)
- isa - สถาปัตยกรรมชุดคำสั่ง (สถาปัตยกรรมชุดคำสั่ง) Obov'yazkovo เลื่อนเพื่อระบุ DW_ISA_ARM_thumb สำหรับ ARM Cortex M3!
- ผู้เลือกปฏิบัติ หนึ่งตำแหน่ง (ไฟล์ แถว stompchik) ของรหัสเอาต์พุตสามารถใช้กับคำสั่งเครื่องต่างๆ ได้ ในช่วงเวลาดังกล่าว สำหรับชุดคำสั่งดังกล่าว จำเป็นต้องติดตั้งตัวแยกความแตกต่าง ไม่มีพฤติกรรมดังกล่าว แต่สามารถเป็น 0 ได้
เมื่อคุณทำเสร็จแล้ว ฟังก์ชัน dwarf_lne_end_sequence จะสิ้นสุดขั้นตอน:
Dwarf_Unsigned dwarf_lne_end_sequence (Dwarf_P_Debug dbg, ที่อยู่ Dwarf_Addr; Dwarf_Error *ข้อผิดพลาด)
- ที่อยู่ - ที่อยู่ของคำสั่งเครื่องเธรด
ซึ่งเราทำการสร้างขั้นตอนให้เสร็จสมบูรณ์
การสร้างการเปลี่ยนแปลงและค่าคงที่
Zagalom zminnі dosi เรียบง่าย พวกเขามี є іm'ya ซึ่งเป็นสถานที่แห่งหน่วยความจำ (หรือรีจิสเตอร์ของโปรเซสเซอร์) ซึ่งพวกเขารู้ข้อมูลของพวกเขา เช่นเดียวกับประเภทของข้อมูล ราวกับว่ามีการเปลี่ยนแปลงไปทั่วโลก - їїพ่อสามารถเป็น Odinitsa Compilation เช่นเดียวกับในท้องถิ่น - มหาวิทยาลัยอื่น (โดยเฉพาะอย่างยิ่งพารามิเตอร์ของขั้นตอนจะถูกนำมาพิจารณาพวกเขาสามารถเป็นขั้นตอนได้) นอกจากนี้ยังสามารถระบุได้ว่ามีการเปลี่ยนแปลงของเสียงในไฟล์ใดในแถวและคอลัมน์ในวิธีที่ง่ายที่สุด ค่าของการเปลี่ยนแปลงเป็นที่รู้จักสำหรับแอดเดรสคงที่บางตัว แต่การเปลี่ยนแปลงจำนวนมากถูกสร้างขึ้นแบบไดนามิกเมื่อป้อนโพรซีเดอร์บนสแต็กหรือรีจิสเตอร์ และบางครั้งการคำนวณแอดเดรสของค่าอาจไม่ใช่ เล็กน้อย มาตรฐานมีกลไกในการอธิบายว่าค่าของการเปลี่ยนแปลงอยู่ที่ใด - นิพจน์ที่อยู่ (นิพจน์ตำแหน่ง) ที่อยู่ viraz - ราคาของคำแนะนำในการพิมพ์ (ค่าคงที่ DW_OP_хххх) สำหรับจักรเย็บผ้าแบบป้อม ในความเป็นจริงราคาของ mov พร้อมการดีบัก ขั้นตอนและการดำเนินการทางคณิตศาสตร์ ฉันไม่สามารถย้อนกลับคำพูดของฉันได้ จริง ๆ แล้วเราเรียกว่าคำแนะนำเล็กน้อยเท่านั้น:
- DW_OP_addr - ระบุที่อยู่การเปลี่ยนแปลง
- DW_OP_fbreg - ระบุการเปลี่ยนแปลงการลงทะเบียนฐาน (ตั้งชื่อตัวบ่งชี้สแต็ค)
- DW_OP_reg0… DW_OP_reg31 - บ่งบอกถึงการเปลี่ยนแปลงโดยการลงทะเบียนที่เลือก
ฟังก์ชันของการสร้างหน้าต่างที่อยู่ว่างจะเปลี่ยนคำอธิบายหรือ 0 สำหรับการให้อภัย:
Dwarf_Expr dwarf_new_expr (Dwarf_P_Debug dbg, Dwarf_Error *ข้อผิดพลาด)
ในการเพิ่มคำอธิบายให้กับไวรัส จำเป็นต้องรวมฟังก์ชัน dwarf_add_expr_gen:
Dwarf_Unsigned dwarf_add_expr_gen (Dwarf_P_Expr expr, Dwarf_Small opcode, Dwarf_Unsigned val1, Dwarf_Unsigned val2, Dwarf_Error *ข้อผิดพลาด)
- opcode - รหัสการดำเนินการ ค่าคงที่ DW_OP_хххх
- val1, val2 – พารามิเตอร์คำสั่ง (div. Standard)
สำหรับการตั้งค่าที่ชัดเจนของที่อยู่ที่สามารถเปลี่ยนแปลงได้ การเปลี่ยนแปลงที่อยู่ข้างหน้าเกิดจากฟังก์ชัน dwarf_add_expr_addr:
Dwarf_Unsigned dwarf_add_expr_addr (Dwarf_P_Expr expr, Dwarf_Unsigned address, Dwarf_Signed sym_index, Dwarf_Error *ข้อผิดพลาด)
- expr - คำอธิบายของที่อยู่ virase ซึ่งได้รับคำแนะนำ
- ที่อยู่ - เปลี่ยนที่อยู่
- sym_index - ดัชนีสัญลักษณ์ในตาราง Neobov'viscous สามารถส่งได้ 0
คุณสามารถเพิ่มที่อยู่ไวรัสลงในไซต์ได้โดยใช้ฟังก์ชัน dwarf_add_AT_location_expr:
Dwarf_P_Attribute dwarf_add_AT_location_expr (Dwarf_P_Debug dbg, เจ้าของ Dwarf_P_Die, Dwarf_Half attr, Dwarf_P_Expr loc_expr, Dwarf_Error *ข้อผิดพลาด)
- เจ้าของ - vuzol ซึ่ง viraz สามารถเข้าถึงได้
- attr - คุณลักษณะ (ครั้ง DW_AT_location)
- loc_expr - จัดการกับไวรัสที่อยู่ที่สร้างไว้ก่อนหน้านี้
การเปลี่ยนแปลง (เช่นเดียวกับพารามิเตอร์ขั้นตอน) และค่าคงที่ - โหนดหลักที่มีแท็ก DW_TAG_variable, DW_TAG_formal_parameter และ DW_TAG_const_type เป็นทางเลือก คุณต้องมีคุณสมบัติดังต่อไปนี้:
- เปลี่ยน/ชื่อคงที่ (ฟังก์ชัน dwarf_add_AT_name, div. "สร้างแอตทริบิวต์ของโหนด")
- หมายเลขแถวของไฟล์ ประกาศการเปลี่ยนแปลง (แอตทริบิวต์ DW_AT_decl_line) ฟังก์ชัน dwarf_add_AT_unsigned_const (div. "สร้างแอตทริบิวต์ของโหนด")
- ดัชนีชื่อไฟล์ (แอตทริบิวต์ DW_AT_decl_file) ฟังก์ชัน dwarf_add_AT_unsigned_const (div. "สร้างแอตทริบิวต์ของโหนด")
- ประเภทข้อมูลเปลี่ยนแปลง/คงที่ (แอตทริบิวต์ DW_AT_type - ตั้งค่าก่อนประเภทการสร้าง div. "ประเภทข้อมูลที่สร้างขึ้น")
- ที่อยู่ virase (div. vishche) - จำเป็นสำหรับการเปลี่ยนแปลงหรือพารามิเตอร์ขั้นตอน
- หรือค่าคงที่ (แอตทริบิวต์ DW_AT_const_value, div. "สร้างแอตทริบิวต์ของโหนด")
การสร้างส่วนที่มีข้อมูลภาษี
หลังจากสร้างโหนดทั้งหมดของต้นไม้ของ nalagodzhuvalnoї іnformatsії คุณสามารถดำเนินการสร้างส่วนเอลฟ์กับมันได้ มีสองขั้นตอน:- เราจำเป็นต้องเรียกใช้ฟังก์ชัน dwarf_transform_to_disk_form กลับไปกลับมา เหมือนกับที่เราเขียนฟังก์ชันการเรียกกลับเพื่อสร้างส่วนเอลฟ์ที่จำเป็นสำหรับส่วนสกิน
- สำหรับส่วนสกิน ฟังก์ชัน dwarf_get_section_bytes จะส่งคืนข้อมูลให้เรา เนื่องจากจำเป็นต้องจดส่วนที่เกี่ยวข้อง
dwarf_transform_to_disk_form (Dwarf_P_Debug dbg, ข้อผิดพลาด Dwarf_Error*)
แปลข้อมูลที่กำหนดเองที่เราสร้างขึ้นเป็นรูปแบบไบนารี แต่อย่าเขียนอะไรลงดิสก์ โปรดกลับมาหาเราในส่วนเอลฟ์ที่สร้างขึ้นจำนวนมากหรือ DW_DLV_NOCOUNT สำหรับการให้อภัย สำหรับส่วนของสกิน จะมีการเรียกใช้ฟังก์ชันการเรียกกลับ ซึ่งถูกส่งผ่านในระหว่างการเริ่มต้นไลบรารีไปยังฟังก์ชัน dwarf_producer_init_c คุณสามารถเขียนฟังก์ชันนี้ได้เอง Її ข้อกำหนดมีดังนี้:
typedef int (*Dwarf_Callback_Func_c)(ชื่อถ่าน*, ขนาด int, ประเภท Dwarf_Unsigned, แฟล็ก Dwarf_Unsigned, ลิงก์ Dwarf_Unsigned, ข้อมูล Dwarf_Unsigned, Dwarf_Unsigned* sect_name_index, void * user_da,
- ชื่อ - ชื่อของส่วนเอลฟ์ วิธีสร้าง
- ขนาด – ขนาดส่วน
- ประเภท - ประเภทส่วน
- ธง - ธงส่วน
- ลิงค์ - ฟิลด์ลิงค์ส่วน
- ข้อมูล - ฟิลด์ข้อมูลส่วน
- sect_name_index – เลือกหมุนดัชนีส่วนด้วยการย้ายตำแหน่ง (ไม่ผูกมัด)
- user_data - ส่งถึงเราเช่นนี้เนื่องจากโยคะของฉันถูกตั้งค่าในฟังก์ชั่นการเริ่มต้นของไลบรารี
- ข้อผิดพลาด - คุณสามารถส่งรหัสอภัยโทษได้ที่นี่
- สร้างส่วนใหม่ (ฟังก์ชัน elf_newscn, div. สร้างส่วน)
- สร้างส่วนหัวของส่วน (ฟังก์ชัน elf32_getshdr, ibid.)
- จำ yogo ได้อย่างถูกต้อง (div. ibid.) ง่ายมาก เนื่องจากฟิลด์ส่วนหัวตรงกับพารามิเตอร์ของฟังก์ชันของเรา ฟิลด์ sh_addr, sh_offset, sh_entsize ถูกตั้งค่าเป็น 0 และ sh_addralign เป็น 1
- หมุนดัชนีของส่วนที่สร้างขึ้น (ฟังก์ชัน elf_ndxscn, div. "section.symtab") หรือ -1 สำหรับการให้อภัย (โดยการตั้งค่ารหัสให้อภัยในข้อผิดพลาด)
- นอกจากนี้ ยังเป็นความผิดของเราที่ข้ามส่วน ".rel" (ในวิวพอร์ตของเรา) ด้วยการเปลี่ยน 0 เมื่อเปิดฟังก์ชัน
- สร้างข้อมูลเพื่อเขียนลงในส่วนโดยใช้ฟังก์ชัน dwarf_get_section_bytes:
Dwarf_Ptr dwarf_get_section_bytes (Dwarf_P_Debug dbg, Dwarf_Signed dwarf_section, Dwarf_Signed *elf_section_index, Dwarf_Unsigned *ความยาว, Dwarf_Error* ข้อผิดพลาด)- dwarf_section - หมายเลขส่วน อาจอยู่ในช่วง 0..n โดยที่ n คือตัวเลขที่ส่งคืนให้เราโดยฟังก์ชัน dwarf_transform_to_disk_form
- elf_section_index - หมุนดัชนีส่วน จำเป็นต้องเขียนข้อมูลลงในกล่อง
- ความยาว - dozhina tsikh danih
- ข้อผิดพลาด - อย่าทวีต
หากไม่มีส่วนให้พับแล้ว) - สร้างตัวจัดการข้อมูลของส่วนการสตรีม (ฟังก์ชัน elf_newdata, div. สร้างส่วน) และบันทึก (div. ibid.) การตั้งค่า:
- d_buf - ตัวบ่งชี้ข้อมูลที่เรานำมาจากฟังก์ชันส่งต่อ
- d_size - rozmir tsikh danih (อ้างแล้ว)
เสร็จสิ้นการทำงานกับห้องสมุด
หลังจากสร้างส่วนต่างๆ คุณสามารถทำให้หุ่นยนต์เสร็จได้ด้วยฟังก์ชัน libdwarf dwarf_producer_finish:Dwarf_Unsigned dwarf_producer_finish (Dwarf_P_Debug dbg, ข้อผิดพลาด Dwarf_Error*)
ฟังก์ชันเปลี่ยน DW_DLV_NOCOUNT สำหรับการให้อภัย
ฉันเคารพว่าขั้นตอนนี้จะไม่ถูกบันทึกลงในแผ่นดิสก์ การบันทึกจำเป็นต้องทำงานสำหรับฟังก์ชันเพิ่มเติมของการแจกจ่าย "การสร้าง ELF - การบันทึกไปยังไฟล์"
วิสโนวอค
ทุกอย่างอยู่ที่ใครฉันทำซ้ำการสร้าง nalagodzhuvalnoi іnformatsiї - หัวข้อนั้นยอดเยี่ยมอยู่แล้วและฉันไม่ได้แตะต้องหัวข้อที่หลากหลาย แต่แสดงเฉพาะม่านเท่านั้น Bazhayuchi สามารถมองด้วยความไม่ประมาท
ทันทีที่คุณมีอาหาร ฉันจะพยายามเป็นพยานถึงพวกเขา
สำหรับการมองเห็นในคอมพิวเตอร์ที่ติดตั้ง โปรแกรมแอนตี้ไวรัสเป็นไปได้ เป็นไปได้ สแกนไฟล์ทั้งหมดในคอมพิวเตอร์รวมถึงไฟล์สกิน okremo. คุณสามารถสแกนไฟล์ใดก็ได้โดยคลิกขวาที่ไฟล์แล้วเลือกตัวเลือกตรวจสอบเพื่อตรวจสอบไฟล์เพื่อหาไวรัส
ตัวอย่างเช่นใครเห็นเด็กน้อย ไฟล์ my-file.elfจากนั้นคลิกขวาที่ไฟล์ที่ต้องการ แล้วเลือกตัวเลือกในเมนูไฟล์ "สแกนเพื่อขอความช่วยเหลือ AVG". เมื่อคุณเลือกตัวเลือกนี้ AVG Antivirus จะถูกขอให้สแกนไฟล์เพื่อหาไวรัส
บางครั้งการให้อภัยอาจถูกตำหนิในผลลัพธ์ การติดตั้งซอฟต์แวร์ไม่ถูกต้องเกี่ยวโยงกับปัญหาอะไรได้บ้าง ไวนิล คืออะไร ในกระบวนการติดตั้ง คุณสามารถตั้งค่าระบบปฏิบัติการของคุณ เชื่อมโยงไฟล์ ELF ของคุณกับซอฟต์แวร์ที่ถูกต้องคายชื่อดังกล่าว "เชื่อมโยงนามสกุลไฟล์".
บางครั้งเรียบง่าย การติดตั้ง Dolphin (โปรแกรมจำลอง) อีกครั้งคุณสามารถแก้ปัญหาของคุณได้โดยเรียก ELF จาก Dolphin (โปรแกรมจำลอง) อย่างถูกต้อง ในกรณีอื่น ๆ ปัญหาเกี่ยวกับความสัมพันธ์ของไฟล์สามารถถูกตำหนิได้ การเขียนโปรแกรมซอฟต์แวร์ที่น่ารังเกียจผู้ค้าปลีก และคุณอาจต้องติดต่อผู้ค้าปลีกเพื่อขอความช่วยเหลือเพิ่มเติม
ภราดา:ลองอัปเดต Dolphin (โปรแกรมจำลอง) กับเวอร์ชันที่เหลือเพื่อดูว่ามีการติดตั้งการอัปเดตที่เหลือหรือไม่
อาจจะชัดเจน แต่บ่อยครั้ง ตรงกลาง ไฟล์ ELF เองอาจเป็นสาเหตุของปัญหา. หากคุณได้รับไฟล์ผ่านทางไฟล์แนบทางอีเมล หรือคุณได้บันทึกไฟล์จากเว็บไซต์ และกระบวนการจับภาพถูกขัดจังหวะ (เช่น เปิดการถ่ายทอดสดหรือด้วยเหตุผลอื่นบางประการ) ไฟล์อาจเสียหายได้. หากเป็นไปได้ ให้ลองทำสำเนาไฟล์ ELF ใหม่แล้วลองอีกครั้ง
อย่างระมัดระวัง:ไฟล์ Poshkodzhenie อาจทำให้เกิดการอุดตันที่ตามมาในด้านหน้า หรือแม้ว่าจะเป็นโปรแกรมฟลุคบนพีซีของคุณก็ตาม สิ่งสำคัญยิ่งกว่าคือต้องอัปเดตคอมพิวเตอร์ของคุณด้วยการอัปเดตป้องกันไวรัสอยู่เสมอ
เช่นเดียวกับไฟล์ ELF ของคุณ ปัญหาเกี่ยวกับความปลอดภัยของฮาร์ดแวร์ในคอมพิวเตอร์ของคุณคุณอาจต้องเปิดไฟล์ อัปเดตไดรเวอร์อุปกรณ์, pov'yazanih іz cim ครอบครอง
อะไรคือปัญหา ดังขึ้นตามประเภทของไฟล์มัลติมีเดีย, yakіนอนลงในรูปแบบของโซลูชันความปลอดภัยของฮาร์ดแวร์ที่ประสบความสำเร็จตรงกลางคอมพิวเตอร์เช่น การ์ดเสียงหรือการ์ดแสดงผล. ตัวอย่างเช่น ถ้าคุณต้องการเปิดไฟล์เสียง หากคุณไม่สามารถเปิดได้ คุณอาจต้องใช้ อัปเดตไดรเวอร์การ์ดเสียง.
ภราดา:ดังนั้นเมื่อพยายามเปิดไฟล์ ELF คุณจะยอมรับ การแจ้งเตือนการให้อภัย ไฟล์ pov'yazanu z.SYS, ปัญหา, ymovіrno, อาจจะเป็น buti เชื่อมต่อกับ poshkogenimi หรือไดรเวอร์อุปกรณ์ที่ล้าสมัยเนื่องจากจำเป็นต้องเปลี่ยน กระบวนการนี้สามารถอำนวยความสะดวกได้ด้วยความช่วยเหลือของซอฟต์แวร์สำหรับอัพเดตไดรเวอร์ เช่น DriverDoc
เด็กน้อยแก้ปัญหาอย่างไรและคุณยังคงมีปัญหาในการเปิดไฟล์ ELF แต่อาจเกี่ยวข้องกับ จำนวนทรัพยากรระบบที่มีอยู่. สำหรับไฟล์ ELF บางเวอร์ชัน คุณอาจต้องการทรัพยากรจำนวนมาก (เช่น หน่วยความจำ / RAM แรงดันการแจงนับ) สำหรับฮาร์ดไดรฟ์ในคอมพิวเตอร์ของคุณ ปัญหาดังกล่าวมักเกิดขึ้นเนื่องจากคุณสามารถดาวน์โหลดฮาร์ดแวร์คอมพิวเตอร์เครื่องเก่าได้อย่างง่ายดายโดยไม่มีการรักษาความปลอดภัย และในขณะเดียวกันก็เติมระบบปฏิบัติการใหม่
ปัญหาดังกล่าวสามารถถูกตำหนิได้ หากเป็นสิ่งสำคัญที่คอมพิวเตอร์จะไม่ทำงาน เศษระบบปฏิบัติการ (บริการอื่น ๆ ที่ทำงานในพื้นหลัง) สามารถ ประหยัดทรัพยากรจำนวนมากเพื่ออ่านไฟล์ ELF. ลองปิดโปรแกรมทั้งหมดบนพีซีของคุณ เปิดไฟล์เกม Nintendo Wii ก่อน เมื่อใช้ทรัพยากรทั้งหมดที่มีในคอมพิวเตอร์ของคุณ คุณจะมีสมองที่ดีที่สุดสำหรับการพยายามเปิดไฟล์ ELF
ยัคโช วี vikonali ทั้งหมดที่อธิบายไว้ข้างต้น crokiและไฟล์ ELF ของคุณไม่แสดงเหมือนเมื่อก่อน คุณอาจต้อง การต่ออายุการครอบครอง. У більшості випадків, навіть при використанні старих версій обладнання, обчислювальна потужність може бути більш ніж достатньою для більшості додатків користувача (якщо ви не виконуєте багато ресурсомісткої роботи процесора, такий як 3D-рендеринг, фінансове/наукове моделювання або інтенсивна мультимедійна робота) . ในลักษณะดังกล่าว ไม่สามารถเคลื่อนย้ายได้อย่างสมบูรณ์ เพื่อให้คอมพิวเตอร์ของคุณไม่ได้รับหน่วยความจำที่จำเป็น(มักเรียกว่า "RAM" หน่วยความจำปฏิบัติการ chi) การตั้งเวลาไฟล์
เราหวังว่าพวกเขาจะช่วยคุณแก้ปัญหาเกี่ยวกับไฟล์ ELF หากคุณไม่ทราบว่าคุณสามารถดาวน์โหลดโปรแกรมจากรายการของเราได้ที่ไหน คลิกที่ลิงค์ (ชื่อโปรแกรม) - คุณจะทราบข้อมูลรายงานเกี่ยวกับตำแหน่งที่ตั้ง ดาว ดาวน์โหลดเวอร์ชันการติดตั้งที่ปลอดภัยของโปรแกรมที่ต้องการ
เราสามารถช่วยคุณด้วยคำแนะนำเฉพาะเกี่ยวกับราคาหรือโภชนาการที่ใกล้เคียงกัน:
- จะเปิดไฟล์ที่มีนามสกุล ELF ได้อย่างไร?
- จะแปลงไฟล์ ELF เป็นรูปแบบอื่นได้อย่างไร?
- ส่วนขยายของรูปแบบ ELF คืออะไร
- โปรแกรมใดที่สามารถให้บริการไฟล์ ELF ได้
จากการตรวจสอบเนื้อหาในอีกด้านหนึ่ง คุณไม่ได้นำหลักฐานที่เพียงพอในสิ่งเดียวกันนี้ออกจากการส่งอาหาร หมายความว่าข้อมูลเกี่ยวกับไฟล์ ELF ที่ให้ไว้ที่นี่ไม่ถูกต้อง ติดต่อกับเรา แบบฟอร์มการติดต่อ vikoristovuyuchi และเขียน ข้อมูลอะไรที่คุณไม่รู้
อะไรอีกที่อาจทำให้เกิดปัญหา?
อาจมีสาเหตุหลายประการที่ทำให้คุณไม่สามารถเปิดไฟล์ ELF ได้ (ไม่ใช่เฉพาะโปรแกรมทั่วไปเท่านั้น)
เพิร์ช- ไฟล์ ELF อาจเชื่อมต่อไม่ถูกต้อง (เสียสติ) จากภาคผนวกที่ติดตั้งสำหรับการบำรุงรักษานี้ ในเวลานี้ คุณต้องเปลี่ยนลิงก์ของคุณโดยอิสระ ดังนั้น ฉันสามารถคลิกขวาที่ปุ่มหมีบนไฟล์ ELF ซึ่งจำเป็นต้องแก้ไข คลิกตัวเลือก "Vіdkritiเพื่อขอความช่วยเหลือ"จากนั้นเลือกโปรแกรมจากรายการตามที่เราติดตั้ง ในกรณีที่เกิดปัญหาดังกล่าว คงต้องโทษไฟล์ ELF อีกครั้ง
ด้วยวิธีที่แตกต่างกัน- ไฟล์ที่คุณต้องการเปิดคุณสามารถใช้งานได้ ในเวลานี้จะเป็นการดีกว่าที่จะทราบเวอร์ชันใหม่หรือดาวน์โหลดอีกครั้งจาก dzherel เดียวกัน (อาจเป็นเพราะไดรฟ์ในเซสชั่นหน้าการจับภาพไฟล์ ELF ไม่สิ้นสุดและไม่สามารถป้อนไวน์ได้อย่างถูกต้อง ).
คุณต้องการที่จะช่วย?
หากคุณมีข้อมูลเพิ่มเติมเกี่ยวกับการขยายไฟล์ ELF เรายินดีที่จะแบ่งปันกับ coristuvachi ของไซต์ของเรา รีบกรอกแบบฟอร์มและส่งข้อมูลของคุณเกี่ยวกับไฟล์ ELF