dl_iterate_phdr(3)

الاسم
dl_iterate_phdr - التجول في قائمة الكائنات المشتركة

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#define _GNU_SOURCE         /* انظر feature_test_macros(7) */
#include <link.h>

int dl_iterate_phdr(
         typeof(int (struct dl_phdr_info *info, size_t size, void *data))
             *callback,
         void *data);

الوصف
تسمح الدالة dl_iterate_phdr() للتطبيق بالاستعلام وقت التشغيل لمعرفة أي الكائنات المشتركة تم تحميلها، والترتيب الذي حُمّلت به.

تتجول الدالة dl_iterate_phdr() في قائمة الكائنات المشتركة للتطبيق وتستدعي الدالة callback مرة لكل كائن، حتى تتم معالجة جميع الكائنات المشتركة أو تُرجع callback قيمة غير صفرية.

تتلقى كل استدعاء لـ callback ثلاث وسائط: info، وهو مؤشر لبنية تحتوي معلومات عن الكائن المشترك؛ size، وهو حجم البنية المشار إليها بـ info؛ و data، وهو نسخة من أي قيمة مررها البرنامج المستدعي كالوسيطة الثانية (المسماة أيضًا data) في استدعاء dl_iterate_phdr().

الوسيطة info هي بنية من النوع التالي:

    struct dl_phdr_info {
        ElfW(Addr)        dlpi_addr;  /* عنوان قاعدة الكائن */
        const char       *dlpi_name;  /* اسم الكائن (منتهٍ بصفر) */
        const ElfW(Phdr) *dlpi_phdr;  /* مؤشر لمصفوفة رؤوس برامج ELF
                                         لهذا الكائن */
        ElfW(Half)        dlpi_phnum; /* عدد العناصر في dlpi_phdr */

        /* الحقول التالية أُضيفت في glibc 2.4، بعد توفر النسخة الأولى
           من هذه البنية. تحقق من الوسيطة size الممررة إلى
           استدعاء dl_iterate_phdr callback لتحديد ما إذا كان كل عضو لاحق متاحًا. */

        unsigned long long dlpi_adds;
                        /* يُزاد عند إضافة كائن جديد */
        unsigned long long dlpi_subs;
                        /* يُزاد عند إزالة كائن */
        size_t dlpi_tls_modid;
                        /* إذا كان هناك مقطع PT_TLS، معرف وحدته المستخدم
                           في إعادة توطين TLS، وإلا صفر */
        void  *dlpi_tls_data;
                        /* عنوان مثيل الخيط المستدعي لمقطع PT_TLS
                           لهذه الوحدة، إذا كان لديها واحد وتم تخصيصه
                           في الخيط المستدعي، وإلا مؤشر فارغ */
    };

(تحول تعريف الماكرو ElfW() وسيطته إلى اسم نوع بيانات ELF مناسب لبنية العتاد. على سبيل المثال، على منصة 32 بت، يُنتج ElfW(Addr) اسم نوع البيانات Elf32_Addr. يمكن العثور على مزيد من المعلومات حول هذه الأنواع في ملفي الرأس <elf.h> و <link.h>.)

يشير الحقل dlpi_addr إلى عنوان قاعدة الكائن المشترك (أي الفرق بين عنوان الذاكرة الافتراضية للكائن المشترك وإزاحة ذلك الكائن في الملف الذي حُمّل منه). الحقل dlpi_name هو سلسلة محارف منتهية بصفر تعطي اسم المسار الذي حُمّل منه الكائن المشترك.

لفهم معنى الحقلين dlpi_phdr و dlpi_phnum، يجب أن ندرك أن الكائن المشترك ELF يتكون من عدد من المقاطع، لكل منها رأس برنامج مقابل يصف المقطع. الحقل dlpi_phdr هو مؤشر لمصفوفة رؤوس البرامج لهذا الكائن المشترك. الحقل dlpi_phnum يشير إلى حجم هذه المصفوفة.

رؤوس البرامج هذه هي بنى من الشكل التالي:

    typedef struct {
        Elf32_Word  p_type;    /* نوع المقطع */
        Elf32_Off   p_offset;  /* إزاحة المقطع في الملف */
        Elf32_Addr  p_vaddr;   /* عنوان المقطع الافتراضي */
        Elf32_Addr  p_paddr;   /* عنوان المقطع الفعلي */
        Elf32_Word  p_filesz;  /* حجم المقطع في الملف */
        Elf32_Word  p_memsz;   /* حجم المقطع في الذاكرة */
        Elf32_Word  p_flags;   /* أعلام المقطع */
        Elf32_Word  p_align;   /* محاذاة المقطع */
    } Elf32_Phdr;

لاحظ أنه يمكن حساب موقع رأس برنامج معين، x، في الذاكرة الافتراضية باستخدام الصيغة:

    addr == info->dlpi_addr + info->dlpi_phdr[x].p_vaddr;

القيم المحتملة لـ p_type تشمل التالي (انظر <elf.h> لمزيد من التفاصيل):

    #define PT_LOAD         1    /* مقطع برنامج قابل للتحميل */
    #define PT_DYNAMIC      2    /* معلومات الربط الديناميكي */
    #define PT_INTERP       3    /* مفسر البرنامج */
    #define PT_NOTE         4    /* معلومات مساعدة */
    #define PT_SHLIB        5    /* محجوز */
    #define PT_PHDR         6    /* إدخال لجدول الرأس نفسه */
    #define PT_TLS          7    /* مقطع تخزين محلي للخيط */
    #define PT_GNU_EH_FRAME 0x6474e550 /* مقطع GCC .eh_frame_hdr */
    #define PT_GNU_STACK  0x6474e551 /* يشير إلى قابلية تنفيذ المكدس */
    #define PT_GNU_RELRO  0x6474e552 /* للقراءة فقط بعد إعادة التوطين */

قيمة الإرجاع
تُرجع الدالة dl_iterate_phdr() أي قيمة أُرجعت بواسطة آخر استدعاء لـ callback.

السمات
للاطلاع على شرح للمصطلحات المستخدمة في هذا القسم، انظر attributes(7).
الواجهة | السمة | القيمة
dl_iterate_phdr() | سلامة الخيوط | MT-Safe

الإصدارات
توفر أنظمة أخرى متنوعة نسخة من هذه الدالة، على الرغم من اختلاف تفاصيل بنية dl_phdr_info المُرجعة. في BSDs و Solaris، تتضمن البنية الحقول dlpi_addr و dlpi_name و dlpi_phdr و dlpi_phnum بالإضافة إلى حقول أخرى خاصة بالتطبيق.

قد تُضيف الإصدارات المستقبلية من مكتبة C حقولاً إضافية إلى بنية dl_phdr_info؛ في هذه الحالة، تُوفّر الوسيطة size آلية لدالة الاستدعاء لمعرفة ما إذا كانت تُنفّذ على نظام يحتوي على حقول مُضافة.

المعايير
لا شيء.

التاريخ
glibc 2.2.4.

ملاحظات
أول كائن يزوره callback هو البرنامج الرئيس. بالنسبة للبرنامج الرئيس، سيكون الحقل dlpi_name سلسلة محارف فارغة.

أمثلة
يعرض البرنامج التالي قائمة بمسارات الكائنات المُشاركة التي حُمّلت. لكل كائن مُشارك، يُدرج البرنامج بعض المعلومات (العنوان الافتراضي، الحجم، الأعلام، والنوع) لكل قطعة ELF من الكائن.

تُظهر جلسة الصدفة التالية المخرجات التي يُنتجها البرنامج على نظام x86-64. أول كائن مُشارك تُعرض مخرجاته (حيث الاسم سلسلة محارف فارغة) هو البرنامج الرئيس.

    $ ./a.out;
    Name: "" (9 segments)
         0: [      0x400040; memsz:    1f8] flags: 0x5; PT_PHDR
         1: [      0x400238; memsz:     1c] flags: 0x4; PT_INTERP
         2: [      0x400000; memsz:    ac4] flags: 0x5; PT_LOAD
         3: [      0x600e10; memsz:    240] flags: 0x6; PT_LOAD
         4: [      0x600e28; memsz:    1d0] flags: 0x6; PT_DYNAMIC
         5: [      0x400254; memsz:     44] flags: 0x4; PT_NOTE
         6: [      0x400970; memsz:     3c] flags: 0x4; PT_GNU_EH_FRAME
         7: [         (nil); memsz:      0] flags: 0x6; PT_GNU_STACK
         8: [      0x600e10; memsz:    1f0] flags: 0x4; PT_GNU_RELRO
    Name: "linux-vdso.so.1" (4 segments)
         0: [0x7ffc6edd1000; memsz:    e89] flags: 0x5; PT_LOAD
         1: [0x7ffc6edd1360; memsz:    110] flags: 0x4; PT_DYNAMIC
         2: [0x7ffc6edd17b0; memsz:     3c] flags: 0x4; PT_NOTE
         3: [0x7ffc6edd17ec; memsz:     3c] flags: 0x4; PT_GNU_EH_FRAME
    Name: "/lib64/libc.so.6" (10 segments)
         0: [0x7f55712ce040; memsz:    230] flags: 0x5; PT_PHDR
         1: [0x7f557145b980; memsz:     1c] flags: 0x4; PT_INTERP
         2: [0x7f55712ce000; memsz: 1b6a5c] flags: 0x5; PT_LOAD
         3: [0x7f55716857a0; memsz:   9240] flags: 0x6; PT_LOAD
         4: [0x7f5571688b80; memsz:    1f0] flags: 0x6; PT_DYNAMIC
         5: [0x7f55712ce270; memsz:     44] flags: 0x4; PT_NOTE
         6: [0x7f55716857a0; memsz:     78] flags: 0x4; PT_TLS
         7: [0x7f557145b99c; memsz:   544c] flags: 0x4; PT_GNU_EH_FRAME
         8: [0x7f55712ce000; memsz:      0] flags: 0x6; PT_GNU_STACK
         9: [0x7f55716857a0; memsz:   3860] flags: 0x4; PT_GNU_RELRO
    Name: "/lib64/ld-linux-x86-64.so.2" (7 segments)
         0: [0x7f557168f000; memsz:  20828] flags: 0x5; PT_LOAD
         1: [0x7f55718afba0; memsz:   15a8] flags: 0x6; PT_LOAD
         2: [0x7f55718afe10; memsz:    190] flags: 0x6; PT_DYNAMIC
         3: [0x7f557168f1c8; memsz:     24] flags: 0x4; PT_NOTE
         4: [0x7f55716acec4; memsz:    604] flags: 0x4; PT_GNU_EH_FRAME
         5: [0x7f557168f000; memsz:      0] flags: 0x6; PT_GNU_STACK
         6: [0x7f55718afba0; memsz:    460] flags: 0x4; PT_GNU_RELRO

  مصدر البرنامج
    #define _GNU_SOURCE
    #include <link.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>

    static int
    callback(struct dl_phdr_info *info, size_t size, void *data)
    {
        char *type;
        int p_type;

        printf("Name: \"%s\" (%d segments)\n", info->dlpi_name,
               info->dlpi_phnum);

        for (size_t j = 0; j < info->dlpi_phnum; j++) {
            p_type = info->dlpi_phdr[j].p_type;
            type = (p_type == PT_LOAD) ? "PT_LOAD" :
                   (p_type == PT_DYNAMIC) ? "PT_DYNAMIC" :
                   (p_type == PT_INTERP) ? "PT_INTERP" :
                   (p_type == PT_NOTE) ? "PT_NOTE" :
                   (p_type == PT_INTERP) ? "PT_INTERP" :
                   (p_type == PT_PHDR) ? "PT_PHDR" :
                   (p_type == PT_TLS) ? "PT_TLS" :
                   (p_type == PT_GNU_EH_FRAME) ? "PT_GNU_EH_FRAME" :
                   (p_type == PT_GNU_STACK) ? "PT_GNU_STACK" :
                   (p_type == PT_GNU_RELRO) ? "PT_GNU_RELRO" : NULL;

            printf("    %2zu: [%14p; memsz:%7jx] flags: %#jx; ", j,
                   (void *) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr),
                   (uintmax_t) info->dlpi_phdr[j].p_memsz,
                   (uintmax_t) info->dlpi_phdr[j].p_flags);
            if (type != NULL)
                printf("%s\n", type);
            else
                printf("[other (%#x)]\n", p_type);
        }

        return 0;
    }

    int
    main(void)
    {
        dl_iterate_phdr(callback, NULL);

        exit(EXIT_SUCCESS);
    }

انظر أيضًا
ldd(1), objdump(1), readelf(1), dladdr(3), dlopen(3), elf(5), ld.so(8)

مواصفات تنسيق التنفيذ والربط، متوفرة في مواقع متعددة على الإنترنت.

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.