এক্সিকিউটেবলের মতো একই ডিরেক্টরিতে .so খুঁজে পাচ্ছেন না?


45

আমার একটি এক্সিকিউটেবল আছে যা libtest.soডায়নামিকভাবে লিঙ্ক করা প্রয়োজন , তাই আমি তাদের একই ডিরেক্টরিতে রেখেছি, তারপরে:

cd path_to_dir
./binary

তবে এটি পেয়েছি:

error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

libtest.soএক্সিকিউটেবল নিজেই একই ডিরেক্টরিতে যা ইতিমধ্যে এটি খুঁজে পেতে কিভাবে অক্ষম হতে পারে?

উত্তর:


25

লোডার কখনই ভাগ করা অবজেক্টের জন্য বর্তমান ডিরেক্টরিটি পরীক্ষা করে না যদি না এটি স্পষ্টভাবে এর মাধ্যমে পরিচালিত হয় $LD_LIBRARY_PATH। দেখুন ld.so(8)আরো বিস্তারিত জানার জন্য man পৃষ্ঠা।


echo $LD_LIBRARY_PATHআমার মেশিনে খালি :(
লিনাক্সার

এটা সাধারণত হয়।
ইগনাসিও ওয়াজকেজ-আব্রামস

2
এটি গ্রন্থাগারের সন্ধানের জন্য লোডারটির জন্য অতিরিক্ত ডিরেক্টরি নির্দিষ্ট করে।
ইগনাসিও ওয়াজকেজ-আব্রামস

1
* নিক্সের পাথগুলি :সেমিকোলন নয়, কোলন ( ) দ্বারা পৃথক করা হয় ।
ইগনাসিও ওয়াজকেজ-আব্রামস

3
LD_LIBRARY_PATH সাধারণত উত্পাদন একটি দুর্বল পছন্দ। তাড়াতাড়ি হ্যাকের পক্ষে ভাল, এবং ইউনিট পরীক্ষা চলাকালীন আনইনস্টল করা বাইনারিগুলি তাদের ভাগ করা লাইব্রেরিগুলি খুঁজে পেতে সহায়তা করার মতো জিনিস (মনে করুন। / কনফিগার; তৈরি করুন; চেক করুন)। আপনার বাইনারি তৈরি করার সময়, আপনি হয় আপনার লাইব্রেরিটিকে একটি আদর্শ স্থানে রাখতে পারেন (/etc/ld.so.conf এ তালিকাবদ্ধ) বা বাইনারিটি কোথায় দেখতে হবে তা জানাতে লিংকের কাছে -আর পতাকাটি পাস করতে পারেন।
অটোমাথিয়াস

57

আপনি গতিশীল লিংকটিকে কোথায় দেখতে হবে তা জানাতে LD_LIBRARY_PATH সেট করতে পারেন, আরও ভাল বিকল্প রয়েছে। আপনি আপনার ভাগ করা লাইব্রেরিটিকে একটি আদর্শ স্থানে রাখতে পারেন , এই জায়গাগুলির তালিকার জন্য ( /etc/ld.so.confলিনাক্সে) এবং /usr/bin/crle(সোলারিসে) দেখুন

-R <path>আপনার বাইনারি তৈরি করার সময় আপনি লিঙ্কারের কাছে যেতে পারেন , যা <path>আপনার ভাগ করা লাইব্রেরির জন্য স্ক্যান করা ডিরেক্টরিগুলির তালিকাতে যোগ করবে । এখানে একটি উদাহরণ। প্রথমত, সমস্যাটি দেখানো:

libtest.h:

void hello_world(void);

libtest.c:

#include <stdio.h>
void hello_world(void) {
  printf("Hello world, I'm a library!\n");
}

, hello.c:

#include "libtest.h"
int main(int argc, char **argv) {
  hello_world();
}

মেকফাইল (ট্যাবগুলি অবশ্যই ব্যবহার করা উচিত):

all: hello
hello: libtest.so.0
%.o: %.c
        $(CC) $(CFLAGS) -fPIC -c -o $@ $<
libtest.so.0.0.1: libtest.o
        $(CC) -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
libtest.so.0: libtest.so.0.0.1
        ln -s $< $@
clean:
        rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0

এটি চালানো যাক:

$ make
cc  -fPIC -c -o libtest.o libtest.c
cc -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
ln -s libtest.so.0.0.1 libtest.so.0
cc     hello.c libtest.so.0   -o hello
$ ./hello 
./hello: error while loading shared libraries: libtest.so.0: cannot open shared object file: No such file or directory

কিভাবে ঠিক হবে এটা? যোগ -R <path>linker পতাকা করার জন্য (এখানে সেটিংস এর দ্বারা LDFLAGS)।

$ make clean
(...)
$ make LDFLAGS="-Wl,-R -Wl,/home/maciej/src/tmp"
(...)
cc   -Wl,-R -Wl,/home/maciej/src/tmp  hello.c libtest.so.0   -o hello
$ ./hello 
Hello world, I'm a library!

বাইনারিটি দেখে আপনি দেখতে পাবেন যে এটির প্রয়োজন libtest.so.0:

$ objdump -p hello | grep NEEDED
  NEEDED               libtest.so.0
  NEEDED               libc.so.6

বাইনারি নির্দিষ্ট ডিরেক্টরিতে মানক স্থানগুলি বাদে এর গ্রন্থাগারগুলির সন্ধান করবে:

$ objdump -p hello | grep RPATH
  RPATH                /home/maciej/src/tmp

আপনি বাইনারি বর্তমান ডিরেক্টরির মধ্যে চেহারা করতে চান তাহলে, আপনাকে RPATH সেট করতে পারেন $ORIGIN। এটি কিছুটা জটিল, কারণ আপনাকে অবশ্যই নিশ্চিত করতে হবে যে ডলারের চিহ্নটি মেক দ্বারা ব্যাখ্যা করা হয়নি। এটি করার একটি উপায় এখানে:

$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
  RPATH                $ORIGIN
$ ./hello 
Hello world, I'm a library!

1
যদি না ব্যবহার করা হয় make, যেমন ম্যানুয়ালি কল করার সময় g++, খালি স্ট্রিংয়ে প্রসারিত -Wl,-rpath='$ORIGIN'হওয়া $ORIGINথেকে রোধ করতে (একক উদ্ধৃতি নোট করুন) চেষ্টা করুন ।
মরপর্ক

14

আপনার এক্সিকিউটেবলের মতো একই ডিরেক্টরি থেকে ভাগ করা অবজেক্টগুলি লোড করতে, কেবল সম্পাদন করুন:

$ LD_LIBRARY_PATH=. ./binary

দ্রষ্টব্য: এটি আপনার সিস্টেমের LD_LIBRARY_PATH পরিবর্তনশীলটি পরিবর্তন করবে না। পরিবর্তনটি কেবল এটির দ্বারা প্রভাবিত করে এবং কেবল এটিই আপনার প্রোগ্রামটি কার্যকর করে।


4

যে কেউ এখনও উত্তর ছাড়াই লড়াই করে, তার জন্য আমি নীচের পরামর্শের সাথে নিজেকে খুঁজে পেয়েছি:

আপনি ld.so.cache ব্যবহার করে আপডেট করার চেষ্টা করতে পারেন: sudo ldconfig -v

আমার জন্য কাজ করেছেন।


আমার জন্যও কাজ করেছেন।
জোয়েল

3

যে কেউ তাদের বিল্ডিংয়ের জন্য সিএমকে ব্যবহার করেন , আপনি CMAKE_EXE_LINKER_FLAGSনিম্নলিখিতটি সেট করতে পারেন :

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")

এটি বর্তমানের ওয়ার্কিং ডিরেক্টরিতে প্রথমে .so ফাইলগুলি সন্ধান করার জন্য সমস্ত বিল্ড প্রকারের (যেমন, ডিবাগ, রিলিজ, ইত্যাদি ...) জন্য লিঙ্কার পতাকাগুলি যথাযথভাবে প্রচার করবে।


0

গতিশীল লিঙ্কারটি গ্রন্থাগারগুলি কোথায় সন্ধান করবেন তা সিদ্ধান্ত নেবে। লিনাক্সের ক্ষেত্রে, গতিশীল লিংক সাধারণত GNU ld.so(বা এমন একটি বিকল্প যা সাধারণত সামঞ্জস্যের কারণে অভিন্ন আচরণ করবে।

উইকিপিডিয়া থেকে উদ্ধৃতিগুলি:

জিএনইউ সি লাইব্রেরির গতিশীল লিংক নিম্নলিখিত অবস্থানগুলিতে ভাগ করে নেওয়া লাইব্রেরিগুলির জন্য অনুসন্ধান করে:

  1. DT_RPATHবাইনারিটির গতিশীল বিভাগের অ্যাট্রিবিউটের (কোলন-বিচ্ছিন্ন) পাথ উপস্থিত থাকলে এবং DT_RUNPATHবৈশিষ্ট্যটি বিদ্যমান না থাকে।
  2. পরিবেশ পরিবর্তনশীলের (কোলন-বিচ্ছিন্ন) পাথগুলি LD_LIBRARY_PATH, যদি না এক্সিকিউটেবলটি setuid/ setgidবাইনারি হয়, তবে এটি উপেক্ষা করা হয়। LD_LIBRARY_PATHডায়ামিক লিঙ্কারে কল করে ওলরাইড করা যাবে - লাইব্রেরি-পাথ (উদাহরণস্বরূপ /lib/ld-linux.so.2 - লাইব্রেরি-পাথ OME হোম / মাইলিবস মাইপোগ্রাম)।
  3. DT_RUNPATHউপস্থিত থাকলে বাইনারিটির গতিশীল বিভাগের বৈশিষ্ট্যের (কোলন-বিচ্ছিন্ন) পাথগুলি ।
  4. Ldconfig ক্যাশে ফাইলের উপর ভিত্তি করে অনুসন্ধান করুন (প্রায়শই /etc/ld.so.cacheএটিতে অবস্থিত ) যা পূর্বে সংযোজনিত লাইব্রেরি পাথ (সেট দ্বারা নির্ধারিত /etc/ld.so.conf) পাওয়া প্রার্থী লাইব্রেরির সংকলিত তালিকা ধারণ করে । তবে, বাইনারি যদি -z nodefaultlibলিংকার বিকল্পের সাথে সংযুক্ত থাকে তবে ডিফল্ট লাইব্রেরি পাথের লাইব্রেরিগুলি এড়িয়ে যায়।
  5. বিশ্বস্ত ডিফল্ট পথে /libএবং তারপরে /usr/lib। যদি বাইনারিটি -z নোডেফাল্টলিব লিঙ্কার বিকল্পের সাথে সংযুক্ত থাকে তবে এই পদক্ষেপটি এড়িয়ে যায়।

সূত্র: https://en.wikedia.org/wiki/Rpath

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.