কিছু অংশীদারি গ্রন্থাগারগুলি এক্সিকিউটেবলের মতো কেন এবং কীভাবে চালানো যায়?


55

32-বিট লিনাক্স সিস্টেমে এটি শুরু করে

$ /lib/libc.so.6

এবং এটি 64-বিট সিস্টেমে

$ /lib/x86_64-linux-gnu/libc.so.6

শেলের মধ্যে একটি আউটপুট সরবরাহ করে:

GNU C Library stable release version 2.10.1, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.0 20090506 (Red Hat 4.4.0-4).
Compiled on a Linux >>2.6.18-128.4.1.el5<< system on 2009-08-19.
Available extensions:
    The C stubs add-on version 2.1.2.
    crypt add-on version 2.1 by Michael Glad and others
    GNU Libidn by Simon Josefsson
    Native POSIX Threads Library by Ulrich Drepper et al
    BIND-8.2.3-T5B
    RT using linux kernel aio
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.

কেন এবং কীভাবে এটি ঘটে এবং অন্যান্য ভাগ করা লাইব্রেরিতে এটি কীভাবে সম্ভব?

আমি /usr/libএক্সিকিউটেবলগুলি সন্ধানের জন্য তাকিয়েছিলাম এবং খুঁজে পেয়েছি /usr/lib/libvlc.so.5.5.0। এটি চালানো বিভাগগুলির ত্রুটির দিকে পরিচালিত করে । : - /


এটি নিম্নলিখিত সমস্ত উত্তরগুলির সাথে যুক্ত হয়েছে, আমার পুনরুদ্ধারটি হ'ল যদি আপনি একটি ভাগ করা লাইব্রেরিতে x বিট সেট করেন তবে r বিট স্পষ্ট থাকা সত্ত্বেও একটি নির্বাহী থেকে এটি লোড করা সম্ভব ছিল (সম্ভবত এখনও আছে)। সিস্টেম এক্সিকিউটেবল এবং লাইব্রেরিগুলিতে বিশ্ব থেকে বিট নিষিদ্ধ করার জন্য এটি একবারে একটি ভাল সুরক্ষা অনুশীলন হিসাবে বিবেচিত হত। বিস্তৃত মুক্ত উত্সের কারণে, এটি কেবলমাত্র বেনামে ftp ডিরেক্টরিটির / bin / ls এর ক্ষেত্রেই প্রযোজ্য। আমার কাছে, এক্স বিট সেটটি ছেড়ে যাওয়া পুরানো অনুশীলনের একটি দৃশ্যরূপ বলে মনে হচ্ছে।
জোশুয়া

উত্তর:


52

এই লাইব্রেরির একটি main()ফাংশন বা সমতুল্য প্রবেশের পয়েন্ট রয়েছে এবং এটি এমনভাবে সংকলিত হয়েছিল যে এটি এক্সিকিউটেবল এবং শেয়ার্ড অবজেক্ট হিসাবে উভয়ই কার্যকর।

এটি কীভাবে করবেন সে সম্পর্কে একটি পরামর্শ এখানে দেওয়া হয়েছে , যদিও এটি আমার পক্ষে কার্যকর হয় না।

এসও-তে অনুরূপ প্রশ্নের উত্তরে এখানে আরও একটি , যা আমি নির্লজ্জভাবে চুরি করব, সামান্য কৌতুক করব, এবং কিছুটা ব্যাখ্যা যোগ করব।

প্রথমত, আমাদের উদাহরণ লাইব্রেরির জন্য উৎস, test.c:

#include <stdio.h>                  

void sayHello (char *tag) {         
    printf("%s: Hello!\n", tag);    
}                                   

int main (int argc, char *argv[]) { 
    sayHello(argv[0]);              
    return 0;                       
}                   

সংকলন করুন:

gcc -fPIC -pie -o libtest.so test.c -Wl,-E

এখানে, আমরা একটি ভাগ করা লাইব্রেরি ( -fPIC) সংকলন করছি , তবে লিঙ্কারকে বলছি যে এটি একটি নিয়মিত এক্সিকিউটেবল ( -pie), এবং এর প্রতীক টেবিলটি এক্সপোর্টযোগ্য ( -Wl,-E) তৈরি করতে, যাতে এটি কার্যকরভাবে এর সাথে যুক্ত হতে পারে।

এবং, যদিও fileএটি বলবে যে এটি একটি ভাগ করা বস্তু, এটি এক্সিকিউটেবল হিসাবে কাজ করে:

> ./libtest.so 
./libtest.so: Hello!

এখন আমাদের এটি দেখতে দরকার যে এটি সত্যিই গতিশীলভাবে সংযুক্ত করা যেতে পারে। একটি উদাহরণ প্রোগ্রাম program.c,:

#include <stdio.h>

extern void sayHello (char*);

int main (int argc, char *argv[]) {
    puts("Test program.");
    sayHello(argv[0]);
    return 0;
}

ব্যবহারে externআমাদের একটি শিরোলেখ তৈরি করতে হয় ves এখন এটি সংকলন করুন:

gcc program.c -L. -ltest

আমরা এটি কার্যকর করার আগে, আমাদের libtest.soগতিশীল লোডারটির পথ যুক্ত করতে হবে :

export LD_LIBRARY_PATH=./

এখন:

> ./a.out
Test program.
./a.out: Hello!

এবং ldd a.outএর লিঙ্কটি প্রদর্শন করবে libtest.so

উল্লেখ্য আমার সন্দেহ যে কিভাবে এই জন্য glibc আসলে কম্পাইল করা হয়, যেহেতু এটি সম্ভবত জন্য glibc নিজেই হিসাবে হিসাবে পোর্টেবল (দেখুন নয় man gccব্যাপারে -fPICএবং -pieসুইচ), কিন্তু এটা মৌলিক প্রক্রিয়া প্রমান। আসল বিশদগুলির জন্য আপনাকে উত্স মেকফিলটি দেখতে হবে।


1
দুর্দান্ত উত্তর, ধন্যবাদ! :-) আমি nmভাগ করা লাইব্রেরিতে ব্যবহার করার চেষ্টা করেছি , তবে এটি কোনও ডিবাগ সংস্করণ নয়। সুতরাং, কেন libvlcএবং অন্যদের ক্রাশ?
Ho1

1
যেহেতু বেশিরভাগ ভাগ করা লাইব্রেরিগুলি এক্সিকিউটেবল হওয়ার উদ্দেশ্যে নয়, জিএনইউ libcএটি ব্যতিক্রম।
স্বর্ণিলকস

আমি আরও দু'জনকে পেয়েছি: ldএবং libpthread
Ho1

@ হো ld.so1 অন্যান্য উপায়ে বিশেষ। কিছুটা পরিমাণে, এটি সাধারণ গতিযুক্ত-সংযুক্ত এক্সিকিউটেবলের চেয়ে বাস্তব বাস্তব নির্বাহযোগ্য।
র্যান্ডম 832

1
এক্সিকিউটেবল-শেয়ারড-লাইব্রেরি তৈরি করা হলেও উপরোক্ত বিকল্পগুলি অর্থে অসম্পূর্ণ, যখন কিছু এক্সিকিউটেবল এটির সাথে লিঙ্ক করার চেষ্টা করে error বিশদ নমুনার রেফারেন্সটি এখানে যুক্ত হয়েছে: unix.stackexchange.com/a/479334/152034
পরশিশু

21

গিথুব এ র্যান্ডম গ্লিবসি রেপোতে একটি উত্তরের জন্য ডুব দেই। এই সংস্করণটি ফাইলটিতে একটি "ব্যানার" সরবরাহ করে version.c

একই ফাইলে কয়েকটি আকর্ষণীয় পয়েন্ট রয়েছে: __libc_print_versionফাংশন যা স্ট্যান্ডিন একই পাঠ্য এবং প্রতীককে প্রিন্টিং সরবরাহ করে __libc_main (void)যা এন্ট্রি পয়েন্ট হিসাবে নথিভুক্ত থাকে। সুতরাং এই প্রতীকটি লাইব্রেরি চালানোর সময় বলা হয়।

সুতরাং লিঙ্কার / সংকলক কীভাবে জানতে পারে যে এটি ঠিক প্রবেশের পয়েন্ট ফাংশন?

আসুন মেকফাইলে ডুব দিন । লিঙ্কার ফ্ল্যাগগুলিতে আকর্ষণীয় পতাকা রয়েছে:

# Give libc.so an entry point and make it directly runnable itself.
LDFLAGS-c.so += -e __libc_main

সুতরাং এটি লাইব্রেরিতে এন্ট্রি পয়েন্ট নির্ধারণের জন্য লিঙ্কার পতাকা। একটি লাইব্রেরি -e function_nameতৈরি করার সময় আপনি লিঙ্কারের জন্য নির্বাহযোগ্য আচরণ তৈরি করতে পারেন । এটা আসলে কি করে? আসুন ম্যানুয়ালটি দেখুন (কিছুটা তারিখযুক্ত তবে এখনও বৈধ) :

লিঙ্কার কমান্ড ল্যাঙ্গুয়েজে একটি আউটপুট ফাইলে (এর প্রবেশ বিন্দুতে) প্রথম নির্বাহযোগ্য নির্দেশকে সংজ্ঞায়িত করার জন্য একটি আদেশ অন্তর্ভুক্ত করা হয়। এর যুক্তি একটি প্রতীক নাম:

এন্ট্রি (প্রতীক)

প্রতীক অ্যাসাইনমেন্টের মতো, ENTRY কমান্ডটি কমান্ড ফাইলটিতে স্বতন্ত্র কমান্ড হিসাবে অথবা সেকশনস কমান্ডের মধ্যে বিভাগ সংজ্ঞাগুলির মধ্যে স্থাপন করা যেতে পারে - যা আপনার লেআউটটির জন্য সবচেয়ে বেশি অর্থবোধ তৈরি করে।

এন্ট্রি পয়েন্ট নির্বাচন করার বিভিন্ন উপায়ের মধ্যে কেবল ENTRY। আপনি এটি নিম্নলিখিত যে কোনও উপায়ে ইঙ্গিত করতে পারেন (অগ্রাধিকারের উত্থানের ক্রমে দেখানো হয়েছে: তালিকার ওপরে রাইড পদ্ধতিগুলি নীচে নীচের পদ্ধতিগুলিতে)।

the `-e' entry command-line option;
the ENTRY(symbol) command in a linker control script;
the value of the symbol start, if present;
the address of the first byte of the .text section, if present;
The address 0. 

উদাহরণস্বরূপ, আপনি একটি অ্যাসাইনমেন্ট স্টেটমেন্ট সহ একটি এন্ট্রি পয়েন্ট তৈরি করতে এই নিয়মগুলি ব্যবহার করতে পারেন: যদি আপনার ইনপুট ফাইলগুলির মধ্যে কোনও প্রতীক সূচনা সংজ্ঞায়িত না করা হয় তবে আপনি এটি একটি উপযুক্ত মান নির্ধারণ করে কেবল এটি সংজ্ঞায়িত করতে পারেন ---

শুরু = 0x2020;

উদাহরণটি একটি নিখুঁত ঠিকানা দেখায় তবে আপনি কোনও অভিব্যক্তি ব্যবহার করতে পারেন। উদাহরণস্বরূপ, যদি আপনার ইনপুট অবজেক্ট ফাইলগুলি এন্ট্রি পয়েন্টের জন্য আরও কিছু চিহ্ন-নাম কনভেনশন ব্যবহার করে তবে আপনি যে চিহ্নটির শুরুতে ঠিকানাটি অন্তর্ভুক্ত রয়েছে তার মান নির্ধারণ করতে পারেন:

start = other_symbol;

(বর্তমান ডকুমেন্টেশন এখানে পাওয়া যাবে )

সত্যিই ldলিঙ্কার এন্ট্রি পয়েন্ট ফাংশন সহ একটি এক্সিকিউটেবল তৈরি করে যদি আপনি এটিকে কমান্ড লাইন বিকল্প সরবরাহ করেন -e(সর্বাধিক ব্যবহারিক সমাধান), ফাংশন প্রতীক সরবরাহ করেন startবা এসেম্বলারের মধ্যে প্রতীক ঠিকানা ইনজেকশন করুন।

তবে দয়া করে মনে রাখবেন যে অন্যান্য লঙ্কারদের সাথে কাজ করার বিষয়টি স্পষ্টভাবে গ্যারান্টিযুক্ত নয় (আমি জানি না যে এলএলভিমের এলএলডি একই পতাকা রয়েছে কিনা)। কেন এই ফাইলটিতে তথ্য সরবরাহ করা ব্যতীত অন্য উদ্দেশ্যে এটি কার্যকর হবে, আমি সচেতন নই।


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