ข้อผิดพลาด "ไม่มีข้อมูลเวอร์ชัน" จาก linux dynamic linker หมายความว่าอย่างไร


91

ในผลิตภัณฑ์ของเราเราจัดส่งไบนารีลินุกซ์บางตัวที่เชื่อมโยงกับไลบรารีระบบแบบไดนามิกเช่น "libpam" ในระบบลูกค้าบางระบบเราได้รับข้อผิดพลาดต่อไปนี้บน stderr เมื่อโปรแกรมทำงาน:

./authpam: /lib/libpam.so.0: no version information available (required by authpam)

แอปพลิเคชันทำงานได้ดีและรันโค้ดจากไลบรารีไดนามิก นี่ไม่ใช่ข้อผิดพลาดร้ายแรง แต่เป็นเพียงคำเตือน

ฉันคิดว่านี่เป็นข้อผิดพลาดมาจากตัวเชื่อมโยงแบบไดนามิกเมื่อไลบรารีที่ติดตั้งระบบขาดสิ่งที่เรียกใช้งานได้ของเรา ฉันไม่รู้อะไรมากเกี่ยวกับภายในของกระบวนการลิงก์แบบไดนามิก ... และการเข้าสู่หัวข้อนั้นไม่ได้ช่วยอะไรมาก :(

ใครทราบสาเหตุของข้อผิดพลาดนี้ ... จะวินิจฉัยสาเหตุได้อย่างไร? ... และเราจะเปลี่ยนไฟล์ปฏิบัติการเพื่อหลีกเลี่ยงปัญหานี้ได้อย่างไร?

อัปเดต: ลูกค้าอัปเกรดเป็น "การทดสอบ" เดเบียนเวอร์ชันล่าสุดและเกิดข้อผิดพลาดเดียวกัน ดังนั้นจึงไม่ใช่ไลบรารี libpam ที่ล้าสมัย ฉันเดาว่าฉันต้องการที่จะเข้าใจสิ่งที่ผู้เชื่อมโยงกำลังบ่น? ฉันจะตรวจสอบสาเหตุที่แท้จริง ฯลฯ ได้อย่างไร

คำตอบ:


65

"ไม่มีข้อมูลเวอร์ชัน" หมายความว่าหมายเลขเวอร์ชันไลบรารีอยู่ต่ำกว่าบนอ็อบเจ็กต์ที่แชร์ ตัวอย่างเช่นถ้าหมายเลข major.minor.patch ของคุณคือ 7.15.5 บนเครื่องที่คุณสร้างไบนารีและหมายเลข major.minor.patch คือ 7.12.1 บนเครื่องติดตั้ง ld จะพิมพ์คำเตือน

คุณสามารถแก้ไขปัญหานี้ได้โดยการคอมไพล์กับไลบรารี (ส่วนหัวและอ็อบเจ็กต์ที่แชร์) ที่ตรงกับเวอร์ชันอ็อบเจ็กต์ที่แชร์ที่มาพร้อมกับ OS เป้าหมายของคุณ เช่นถ้าคุณจะติดตั้ง RedHat 3.4.6-9 คุณไม่ต้องการคอมไพล์บน Debian 4.1.1-21 นี่เป็นสาเหตุหนึ่งที่การแจกแจงส่วนใหญ่จัดส่งสำหรับหมายเลข linux distro เฉพาะ

มิฉะนั้นคุณสามารถลิงก์แบบคงที่ อย่างไรก็ตามคุณไม่ต้องการทำสิ่งนี้กับบางอย่างเช่น PAM ดังนั้นคุณต้องการติดตั้งสภาพแวดล้อมการพัฒนาที่ตรงกับสภาพแวดล้อมการผลิตของลูกค้าของคุณ (หรืออย่างน้อยก็ติดตั้งและเชื่อมโยงกับเวอร์ชันไลบรารีที่ถูกต้อง)

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

ตัวเลือกสุดท้ายของคุณจะรวบรวมกับไลบรารีที่มีหมายเลขเวอร์ชันรองอื่นโดยใช้สคริปต์การเชื่อมโยงที่กำหนดเอง: http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-linker/scripts html

ในการดำเนินการนี้คุณจะต้องเขียนสคริปต์ที่กำหนดเองและคุณจะต้องมีโปรแกรมติดตั้งแบบกำหนดเองที่รัน ld กับอ็อบเจ็กต์ที่แชร์ของไคลเอ็นต์ของคุณโดยใช้สคริปต์ที่กำหนดเอง สิ่งนี้ต้องการให้ลูกค้าของคุณมี gcc หรือ ld ในระบบการผลิตของตน


22

สิ่งที่ข้อความจาก glibc dynamic linker หมายความว่าจริงๆแล้วไลบรารีที่กล่าวถึง ( /lib/libpam.so.0ในกรณีของคุณ) ไม่มีVERDEFส่วน ELF ในขณะที่ไบนารี ( authpamในกรณีของคุณ) มีข้อกำหนดเวอร์ชันบางVERNEEDส่วนสำหรับไลบรารีนี้ (น่าจะเป็นlibpam.so.0) คุณสามารถดูได้โดยreadelfง่ายเพียงแค่ดู.gnu.version_dและ.gnu.version_rส่วนต่างๆ (หรือขาด)

ดังนั้นจึงไม่ใช่เวอร์ชันสัญลักษณ์ที่ไม่ตรงกันเพราะหากไบนารีต้องการรับเวอร์ชันที่เฉพาะเจาะจงผ่านทางVERNEEDและไลบรารีไม่ได้ระบุไว้ในความเป็นจริงVERDEFนั่นจะเป็นข้อผิดพลาดของฮาร์ดลิงค์เกอร์และไบนารีจะไม่ทำงานเลย (เช่นนี้เทียบกับสิ่งนี้หรือนั้น ) ไบนารีนั้นต้องการบางเวอร์ชัน แต่ไลบรารีไม่ได้ให้ข้อมูลใด ๆ เกี่ยวกับเวอร์ชัน

หมายความว่าอย่างไรในทางปฏิบัติ? โดยปกติแล้วสิ่งที่เห็นในตัวอย่างนี้ไม่มีอะไรเพียงแค่ทำงานโดยไม่สนใจการกำหนดเวอร์ชัน สิ่งต่างๆอาจแตกได้หรือไม่? แน่นอนใช่ดังนั้นคำตอบอื่น ๆ จึงถูกต้องในความจริงที่ว่าควรใช้ไลบรารีเดียวกันในรันไทม์เหมือนกับที่ไบนารีเชื่อมโยงในเวลาสร้าง

ข้อมูลเพิ่มเติมสามารถพบได้ในอูล Dreppers "เอลฟ์รุ่นสัญลักษณ์"


5
ฉันแนะนำให้เรียกใช้ 'readelf -V <exePath>' เพื่อดูส่วนการกำหนดเวอร์ชัน แจ้งให้ทราบทุน V
Rayee Roded

ฉันอนุมานได้ว่านี่เป็นสาเหตุของคำเตือนสำหรับไลบรารี (ระบบเวอร์ชันใหม่กว่า) ที่ฉันสร้างขึ้นเองและติดตั้งในคำนำหน้าแบบขนาน ฉันคิดเสมอว่าเป็นเพราะฉันใช้ LLVM toolchain แต่ฉันเพิ่งสังเกตว่าการสร้างด้วยระบบ gcc ไม่ได้ใส่แท็กเวอร์ชันเหล่านั้นลงในไลบรารีโดยอัตโนมัติ ฉันต้องเพิ่มตัวเลือกผ่าน CFLAGS และ / หรือ LDFLAGS หรือไม่
RJVB

5

Fwiw ฉันมีปัญหานี้เมื่อเรียกใช้ check_nrpe บนระบบที่ติดตั้งระบบตรวจสอบ zenoss เพื่อเพิ่มความสับสนมันทำงานได้ดีในฐานะผู้ใช้รูท แต่ไม่ใช่ผู้ใช้ zenoss

ฉันพบว่าผู้ใช้ zenoss มี LD_LIBRARY_PATH ที่ทำให้ใช้ไลบรารี zenoss ซึ่งออกคำเตือนเหล่านี้ ได้แก่ :

root@monitoring:$ echo $LD_LIBRARY_PATH

su - zenoss
zenoss@monitoring:/root$ echo $LD_LIBRARY_PATH
/usr/local/zenoss/python/lib:/usr/local/zenoss/mysql/lib:/usr/local/zenoss/zenoss/lib:/usr/local/zenoss/common/lib::
zenoss@monitoring:/root$ /usr/lib/nagios/plugins/check_nrpe -H 192.168.61.61 -p 6969 -c check_mq
/usr/lib/nagios/plugins/check_nrpe: /usr/local/zenoss/common/lib/libcrypto.so.0.9.8: no version information available (required by /usr/lib/libssl.so.0.9.8)
(...)
zenoss@monitoring:/root$ LD_LIBRARY_PATH= /usr/lib/nagios/plugins/check_nrpe -H 192.168.61.61 -p 6969 -c check_mq
(...)

อย่างไรก็ตามสิ่งที่ฉันพยายามจะพูด: ตรวจสอบตัวแปรของคุณเช่น LD_LIBRARY_PATH, LD_PRELOAD ฯลฯ ด้วย


3

คุณรวบรวมแอปของคุณอย่างไร คอมไพเลอร์แฟล็กอะไร

จากประสบการณ์ของฉันเมื่อกำหนดเป้าหมายไปยังขอบเขตของระบบ Linux ที่กว้างใหญ่ให้สร้างแพ็คเกจของคุณในเวอร์ชันที่เก่าที่สุดที่คุณยินดีสนับสนุนและเนื่องจากระบบมีแนวโน้มที่จะเข้ากันได้มากขึ้นแอปของคุณจะยังคงทำงานต่อไป อันที่จริงนี่เป็นเหตุผลทั้งหมดสำหรับการกำหนดเวอร์ชันของไลบรารี - รับประกันความเข้ากันได้แบบย้อนหลัง


1

คุณเคยเห็นสิ่งนี้แล้วหรือยัง? สาเหตุน่าจะเป็น libpam ที่เก่ามากในด้านใดด้านหนึ่งซึ่งอาจเกิดจากลูกค้ารายนั้น

หรือลิงก์สำหรับเวอร์ชันอาจขาดหายไป: http://www.linux.org/docs/ldp/howto/Program-Library-HOWTO/shared-libraries.html


ฉันพบสิ่งนั้น แต่มันไม่ได้ช่วยให้เข้าใจสาเหตุจริงๆ ฉันไม่คิดว่ามันเป็นไลบรารี pam เก่าเพราะพวกเขาอัปเดตเป็นการทดสอบเดเบียนล่าสุด

ถ้าอย่างนั้นคุณอาจจะคอมไพล์ในเครื่องเก่า? :) คุณได้ลองคอมไพล์ในเครื่องของลูกค้าแล้วหรือยัง? nondot.org/sabre/Mirrored/libtool-2.1a/libtool_toc.html#TOC36
Vinko Vrsalovic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.