Linux, GNU GCC, ld, สคริปต์เวอร์ชันและรูปแบบไบนารีของ ELF - มันทำงานอย่างไร


13

ฉันพยายามเรียนรู้เพิ่มเติมเกี่ยวกับการกำหนดเวอร์ชันของไลบรารีใน Linux และวิธีการทำให้ทุกอย่างทำงานได้ นี่คือบริบท:

- ฉันมีสองรุ่นของห้องสมุดแบบไดนามิกซึ่งเผยให้เห็นชุดเดียวกันของอินเตอร์เฟซพูดและlibsome1.solibsome2.so

- libsome1.soโปรแกรมที่มีการเชื่อมโยงกับ

- โปรแกรมนี้จะใช้ในการโหลดแบบไดนามิกโมดูลอื่นพูดlibdl.solibmagic.so

- ตอนนี้มีการเชื่อมโยงกับlibmagic.so libsome2.soเห็นได้ชัดโดยไม่ต้องใช้สคริปต์ลิงเกอร์สัญลักษณ์ซ่อนตัวอยู่ในlibmagic.soที่เวลาทำงานทุกสายอินเตอร์เฟซในการได้รับการแก้ไขไปlibsome2.so libsome1.soนี้ได้รับการยืนยันโดยการตรวจสอบค่าส่งกลับโดยเทียบกับมูลค่าของแมโครlibVersion()LIB_VERSION

- ดังนั้นฉันลองถัดไปเพื่อคอมไพล์และเชื่อมโยงlibmagic.soกับสคริปต์ linker ซึ่งซ่อนสัญลักษณ์ทั้งหมดยกเว้น 3 ซึ่งกำหนดไว้ในlibmagic.soและถูกส่งออกโดยมัน ใช้งานได้ ... หรืออย่างน้อยที่สุดlibVersion()และLIB_VERSIONค่าตรงกัน (และรายงานรุ่น 2 ไม่ใช่ 1)

- อย่างไรก็ตามเมื่อโครงสร้างข้อมูลบางอย่างต่อเนื่องเป็นดิสก์ฉันสังเกตเห็นความเสียหายบางอย่าง ในไดเรกทอรีของแอปพลิเคชันหากฉันลบlibsome1.soและสร้างลิงค์ซอฟต์ลิสต์ในตำแหน่งที่จะชี้ไปlibsome2.soทุกอย่างทำงานได้ตามที่คาดหวังและความเสียหายเดียวกันจะไม่เกิดขึ้น

ฉันอดไม่ได้ที่จะคิดว่าสิ่งนี้อาจเกิดขึ้นเนื่องจากความขัดแย้งในการแก้ปัญหาสัญลักษณ์ของลิงเกอร์ ฉันได้ลองหลายสิ่งหลายอย่างเช่นพยายามเชื่อมโยงlibsome2.soเพื่อให้สัญลักษณ์ทั้งหมดเป็นสัญลักษณ์symbol@@VER_2(ซึ่งฉันยังสับสนอยู่เพราะคำสั่งnm -CD libsome2.soยังคงแสดงสัญลักษณ์เป็นsymbolและไม่ใช่symbol@@VER_2) ... ดูเหมือนจะไม่มีอะไรทำงาน !!! ช่วยด้วย!!!!!!


วิธีสุดท้ายของคุณคือวิธีที่ฉันจะเริ่มต้นด้วย และฉันยอมรับว่าการคอร์รัปชั่นนั้นอาจเป็นความสับสนของสัญลักษณ์ น่าเศร้าที่ฉันไม่มีคำตอบให้คุณ
RobotHumans

สิ่งนี้อาจทำได้ดีกว่าดังนั้นแม้ว่าฉันจะไม่เข้าใจที่จะพูดได้อย่างแน่นอน ติดธงทำเครื่องหมายหากคุณต้องการให้เราย้าย
xenoterracide

1
ลองRTLD_LOCALและRTLD_DEEPBINDปักธงในแอพของคุณ ฉันไม่มีเวลาที่จะทดสอบสิ่งนี้ในตอนนี้ แต่มันควรจะทำงานตาม manpage
stribika

คำตอบ:


13

สิ่งนี้ไม่ได้ตอบคำถามของคุณอย่างแน่นอน แต่ ...

ก่อนอื่น ELF คือข้อกำหนดที่ใช้โดย Linux สำหรับไฟล์ปฏิบัติการ (โปรแกรม), ไลบรารีที่แบ่งใช้และไฟล์อ็อบเจ็กต์ซึ่งเป็นไฟล์ระดับกลางที่พบเมื่อรวบรวมซอฟต์แวร์ ไฟล์อ็อบเจ็กต์ลงท้ายด้วย. o ไลบรารีที่ใช้ร่วมกันลงท้ายด้วย. so ตามด้วยตัวเลขศูนย์หรือมากกว่าคั่นด้วยเครื่องหมายจุดและไฟล์ที่ปฏิบัติการได้ไม่มีส่วนขยายใด ๆ ตามปกติ

โดยทั่วไปจะมีสามรูปแบบเพื่อตั้งชื่อไลบรารีที่ใช้ร่วมกันรูปแบบแรกจะสิ้นสุดใน. so ตัวอย่างเช่นไลบรารีที่เรียกว่า readline ถูกเก็บไว้ในไฟล์ชื่อ libreadline.so และอยู่ภายใต้หนึ่งใน / lib, / usr / lib หรือ / usr / local / lib ตามปกติ ไฟล์นั้นจะอยู่เมื่อรวบรวมซอฟต์แวร์ที่มีตัวเลือกเช่น -lreadline -l บอกคอมไพเลอร์เพื่อเชื่อมโยงกับห้องสมุดดังต่อไปนี้ เนื่องจากห้องสมุดเปลี่ยนไปเป็นครั้งคราวมันอาจล้าสมัยดังนั้นห้องสมุดจึงฝังสิ่งที่เรียกว่า SONAME SONAME สำหรับ readline อาจดูเหมือน libreadline.so.2 สำหรับเวอร์ชันหลักที่สำคัญของ libreadline อาจมี readline เวอร์ชันรองจำนวนมากที่เข้ากันได้และไม่ต้องการซอฟต์แวร์ที่จะคอมไพล์ใหม่ readline รุ่นรองอาจมีชื่อว่า libreadline.so.2.14 libreadline ปกติ ดังนั้นเป็นเพียงลิงก์สัญลักษณ์ไปยัง readline เวอร์ชันล่าสุดที่สำคัญที่สุดคือ libreadline.so.2 ในกรณีนี้ libreadline.so.2 เป็นลิงค์สัญลักษณ์ไปยัง libreadline.so.2.14 ซึ่งเป็นไฟล์ที่ใช้งานจริง

SONAME ของไลบรารีถูกฝังอยู่ภายในไฟล์ไลบรารีเอง อยู่ข้างในไฟล์ libreadline.so.2.14 คือสตริง libreadline.so.2 เมื่อโปรแกรมรวบรวมและเชื่อมโยงกับ readline โปรแกรมจะค้นหาไฟล์ libreadline.so และอ่าน SONAME ที่ฝังอยู่ในนั้น ต่อมาเมื่อโปรแกรมถูกดำเนินการจริงมันจะโหลด libreadline.so.2 ไม่ใช่แค่ libreadline.so เนื่องจากเป็น SONAME ที่ถูกอ่านเมื่อมีการเชื่อมโยงครั้งแรก สิ่งนี้ช่วยให้ระบบมีการติดตั้ง readline หลายเวอร์ชันที่เข้ากันไม่ได้และแต่ละโปรแกรมจะโหลดเวอร์ชันหลักที่เหมาะสมซึ่งเชื่อมโยงด้วย นอกจากนี้เมื่ออัปเกรด readline พูดเป็น 2.17 ฉันสามารถติดตั้ง libreadline.so.2.17 ข้างๆไลบรารีที่มีอยู่และเมื่อฉันย้ายลิงค์สัญลักษณ์ libreadline.so.2 จาก libreadline.so.2.13 ไปเป็น libreadline.so.2.17

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