ในstrace
เอาต์พุตพา ธ ไปยังไลบรารีที่เรียกใช้งานการเรียกใช้อยู่ในการเรียกopen()
ใช้ นี่เป็นการเรียกระบบที่ใช้โดยโปรแกรมที่เชื่อมโยงแบบไดนามิกหรือไม่? เกี่ยวกับdlopen()
อะไร open()
ไม่ใช่สายที่ฉันเดาได้ว่าจะมีบทบาทในการทำงานของโปรแกรม
ในstrace
เอาต์พุตพา ธ ไปยังไลบรารีที่เรียกใช้งานการเรียกใช้อยู่ในการเรียกopen()
ใช้ นี่เป็นการเรียกระบบที่ใช้โดยโปรแกรมที่เชื่อมโยงแบบไดนามิกหรือไม่? เกี่ยวกับdlopen()
อะไร open()
ไม่ใช่สายที่ฉันเดาได้ว่าจะมีบทบาทในการทำงานของโปรแกรม
คำตอบ:
dlopen
ไม่ได้เป็นสายระบบมันเป็นฟังก์ชั่นห้องสมุดในห้องสมุด libdl strace
เฉพาะสายระบบแสดงขึ้นใน
บน Linux และบนแพลตฟอร์มอื่น ๆ (โดยเฉพาะอย่างยิ่งที่ใช้รูปแบบ ELF สำหรับ executables) dlopen
จะถูกนำไปใช้โดยการเปิดไลopen()
บรารี่เป้าหมายด้วยการแมปมันเข้ากับหน่วยความจำด้วย มันเป็นส่วนสำคัญอย่างยิ่งที่นี่มันคือสิ่งที่รวมไลบรารีไว้ในพื้นที่ที่อยู่ของกระบวนการดังนั้น CPU จึงสามารถเรียกใช้งานโค้ดได้ แต่คุณต้องไปที่ไฟล์ก่อนที่จะทำได้!mmap()
mmap()
open()
mmap()
ld-linux
ถูกแมปโดยเคอร์เนลเป็นส่วนหนึ่งของการexecve
เรียกระบบ
dlopen ไม่มีส่วนเกี่ยวข้องกับไลบรารีที่แบ่งใช้อย่างที่คุณคิด มีสองวิธีในการโหลดวัตถุที่แชร์:
main
หน้าที่จะเรียกใช้และตั้งค่าพื้นที่กระบวนการของแอปพลิเคชันเพื่อให้แอปพลิเคชันค้นหาฟังก์ชันของไลบรารี วิธีนี้เกี่ยวข้องกับopen()
การซ้อนกันและจากนั้นmmap()
ตามด้วยการตั้งค่าตารางการค้นหาlibdl
จากนั้นคุณ (โดยใช้วิธีแรก) สามารถโทรdlopen()
และdlsym()
ฟังก์ชั่น. ด้วย dlopen คุณจะได้รับการจัดการไปยังห้องสมุดซึ่งคุณสามารถใช้กับ dlsym เพื่อรับฟังก์ชั่นตัวชี้ไปยังฟังก์ชั่นเฉพาะ วิธีนี้มีความซับซ้อนมากกว่าสำหรับโปรแกรมเมอร์มากกว่าวิธีแรก (เนื่องจากคุณต้องทำการตั้งค่าด้วยตนเองแทนที่จะให้ตัวเชื่อมโยงทำมันให้คุณโดยอัตโนมัติ) และมันก็ค่อนข้างบอบบางกว่า (เนื่องจากคุณไม่ได้รับการคอมไพล์ - ตรวจสอบเวลาว่าคุณกำลังเรียกใช้ฟังก์ชันด้วยประเภทอาร์กิวเมนต์ที่ถูกต้องตามที่คุณได้รับในวิธีแรก) แต่ข้อดีคือคุณสามารถเลือกวัตถุที่ใช้ร่วมกันที่จะโหลดในขณะทำงาน (หรือแม้กระทั่งว่าจะโหลดเลย) นี่เป็นอินเทอร์เฟซสำหรับการใช้งานประเภทปลั๊กอิน ในที่สุดอินเทอร์เฟซ dlopen ยังพกพาได้น้อยกว่าวิธีอื่นเนื่องจากกลไกของมันขึ้นอยู่กับการใช้งานตัวเชื่อมโยงแบบไดนามิกที่แน่นอน (ดังนั้น libtool'slibltdl
ซึ่งพยายามแยกความแตกต่างเหล่านี้ออกจากกัน)วันนี้ระบบปฏิบัติการส่วนใหญ่ใช้วิธีการสำหรับไลบรารีที่ใช้ร่วมกันซึ่งเปิดตัวในปลายปี 1987 โดย SunOS-4.0 วิธีนี้ขึ้นอยู่กับการแม็พหน่วยความจำผ่าน mmap ()
จากข้อเท็จจริงที่ว่าในต้นปี 1990 Sun ได้บริจาครหัส a.out เก่า (Solaris ในเวลานั้นเป็น ELF based) แก่ผู้ใช้ FreeBSD และรหัสนี้ในภายหลังได้มอบให้กับระบบอื่น ๆ (รวมถึง Linux) คุณอาจเข้าใจว่าทำไมไม่มีความแตกต่างใหญ่ระหว่างแพลตฟอร์ม
ltrace -S
การวิเคราะห์ตัวอย่างที่น้อยที่สุดแสดงให้เห็นว่าmmap
ใช้ใน glibc 2.23
ใน glibc 2.23, Ubuntu 16.04, รันlatrace -S
บนโปรแกรมขนาดเล็กที่สุดที่ใช้dlopen
กับ:
ltrace -S ./dlopen.out
แสดงให้เห็นว่า:
dlopen("libcirosantilli_ab.so", 1 <unfinished ...>
SYS_open("./x86_64/libcirosantilli_ab.so", 524288, 06267650550) = -2
SYS_open("./libcirosantilli_ab.so", 524288, 06267650550) = 3
SYS_read(3, "\177ELF\002\001\001", 832) = 832
SYS_brk(0) = 0x244c000
SYS_brk(0x246d000) = 0x246d000
SYS_fstat(3, 0x7fff42f9ce30) = 0
SYS_getcwd("/home/ciro/bak/git/cpp-cheat"..., 128) = 54
SYS_mmap(0, 0x201028, 5, 2050) = 0x7f1c323fe000
SYS_mprotect(0x7f1c323ff000, 2093056, 0) = 0
SYS_mmap(0x7f1c325fe000, 8192, 3, 2066) = 0x7f1c325fe000
SYS_close(3) = 0
SYS_mprotect(0x7f1c325fe000, 4096, 1) = 0
ดังนั้นเราจะเห็นได้ทันทีว่าdlopen
โทร+open
mmap
น่ากลัวltrace
เครื่องมือร่องรอยทั้งสายห้องสมุดและระบบโทรศัพท์และดังนั้นจึงเหมาะที่จะตรวจสอบสิ่งที่เกิดขึ้นในกรณีนี้
การวิเคราะห์อย่างใกล้ชิดแสดงให้เห็นว่าopen
ส่งกลับไฟล์ descriptor 3
(อันถัดไปฟรีหลังจาก stdin, out และ err)
read
แล้วใช้ที่บ่งแฟ้ม แต่สิ่งที่ต้องทำทำไมmmap
ข้อโต้แย้ง 's จะถูก จำกัด ให้สี่และเราไม่สามารถดูที่ FD ถูกนำมาใช้มีตั้งแต่ที่เป็นอาร์กิวเมนต์ที่ strace
ยืนยันอย่างที่คาดหวังนั่น3
คือสิ่งนั้นและลำดับของจักรวาลได้รับการฟื้นฟู
วิญญาณผู้กล้าหาญยังสามารถเปลี่ยนเป็น glibc code ได้ แต่ฉันไม่สามารถหาmmap
grep ที่รวดเร็วและขี้เกียจได้
ทดสอบกับนี้ตัวอย่างน้อยที่สุดกับการสร้างต้นแบบบน GitHub
strace
รายงานการเรียกใช้ระบบ (เช่นฟังก์ชั่นที่ใช้งานโดยตรงจากเคอร์เนล) ไลบรารีแบบไดนามิกไม่ใช่ฟังก์ชันเคอร์เนล dlopen
เป็นส่วนหนึ่งของไลบรารี C ไม่ใช่เคอร์เนล การดำเนินการของdlopen
will call open
(ซึ่งเป็นการเรียกระบบ) เพื่อเปิดไฟล์ไลบรารีเพื่อให้สามารถอ่านได้
ltrace
สามารถโทรออกห้องสมุดจะเห็นได้โดยใช้
ltrace -S
สมบูรณ์แบบในการวิเคราะห์สิ่งนี้เนื่องจากมันยังแสดง syscalls: unix.stackexchange.com/a/462710/32558