سؤال

وأنا أكتب برنامج لينكس في C لتحليل الملفات الأساسية التي تنتج من نظام المضمنة. قد تكون الملفات الأساسية endian قليلا (ARM) أو endian كبيرة (MIPS)، وبرنامج لتحليلها قد تكون قيد التشغيل على مجموعة Endian طفيف (x86) وأو endian كبيرة (باور).

ومن خلال النظر في رؤوس أعرف ما إذا كان جوهر هو LE أو BE. أنا أفضل أن برنامجي <م> لا بحاجة إلى معرفة ما إذا كان المضيف تشغيله على القليل أو كبيرة endian، أود أن استخدام API للتعامل مع ذلك بالنسبة لي. إذا لم يكن هناك خيار أفضل، وأعتقد سأبدأ الاعتماد على __BIG_ENDIAN #IFDEF __.

في نواة لينكس لدينا cpu_to_le32 آخرون لتحويل من ترتيب البايت الأصلي إلى endian قليلا، وما إلى ذلك في الفضاء المستخدم هناك htonl وآخرون، التي تحول من مواطن إلى endian كبيرة ولكن ما يعادلها لموطنها endian القليل الذي I يمكن العثور عليها.

ويمكن لأي شخص أن يقترح API مناسبة لمساحة المستخدم؟

تعديل : مجرد أن تكون واضحة، أنا أبحث عن أي API الذي لا يعرف بالفعل ما إذا كان بلدي وحدة المعالجة المركزية endian كبيرة أو صغيرة ومقايضة اعفي وفقا لذلك. أنا لا أريد أن يكون لالقمامة قانون بلدي مع #ifdefs لهذا الغرض. أنا لا تبحث فقط عن مقتطفات الشفرة لمبادلة بايت. شكرا لهؤلاء، لكن ذلك لم يكن نقطة.

هل كانت مفيدة؟

المحلول

وبناء على ما كنت تحاول القيام به فعلا (قراءة ملفات تفريغ الأساسية ELF دون الحاجة إلى القلق حول القضايا endian)، وأعتقد أن استخدام libelf، وهي متاحة على هنا مع البرنامج التعليمي لطيفة <لأ href =" http://people.freebsd.org/~jkoshy/download/libelf/article هتمل "يختلط =" نوفولو noreferrer "> هنا ، سيكون خيارا جيدا.

وهذه المكتبة تعمل بشفافية مع ملفات ELF big- وEndian طفيف ويعمل على ما يرام في لينكس على الرغم من أصول فري التابعة (المعتاد "./configure" و "جعل" التسلسل هو كل ما تحتاج لبنائه). لالتكشير حاولت سبيل المثال "قراءة رأس جدول برنامج" (مع تعديلات طفيفة للحصول عليه لبناء) على ملف أساسية إلى x86 وكذلك ملف أساسية كبير-endian MIPS، يبدو أن "العمل فقط".

نصائح أخرى

و#include <arpa/inet.h> هو لطيف والمحمولة، ولكن يضمن فقط {ntoh,hton}{s,l}. إذا كنت بحاجة إلى التحويلات على القيم 64 بت، أو التقليب endian على كبير-endian (حيث ntoh وhton لا تفعل شيئا)، فإنه لن يكون كافيا.

في لينكس (سي العمومية)، <وأ href = "http://sources.redhat.com/cgi-bin/cvsweb.cgi/~checkout~/libc/string/endian.h؟cvsroot=glibc" يختلط = "noreferrer"> #include <endian.h> توفر ما يلي، يعرف بما يتناسب مع الجهاز الحالي.

htobe16  be16toh    htole16  le16toh
htobe32  be32toh    htole32  le32toh
htobe64  be64toh    htole64  le64toh

في * BSD، <وأ href = "http://cvsweb.se.netbsd.org/cgi-bin/bsdweb.cgi/~checkout~/src/sys/sys/endian.h" يختلط = "noreferrer "> #include <sys/endian.h> يوفر وحدات الماكرو هذه نفسها.

إذا كان لديك الوصول إلى وحدة التشغيل النيون والذاكرة متجاورة (مثال إطار فيديو) هل يمكن تنفيذ swap16 على الإطار باستخدام سجلات ف (128bytes) بهذه الطريقة. وبطبيعة الحال، لديك لمشاهدة لقضايا المواءمة

void swap16(void *__restrict src16)
{
    const void *start = src16;
    const void *end = src16 + FRAME_SIZE;
    asm volatile (
        "1: pld     [%0, #0x100]\n"
        "vld2.8         {q0,q1}, [%0]\n"
        "vmov           q2,q0\n"
        "vst2.8         {q1,q2}, [%0]!\n"
        "cmp            %1,%0\n"
        "bne            1b\n"
        : /* empty output operands */
        : "r" (start), "r" (end)
        : "cc", "memory"
        );
}

إذا كنت معالجة الملف صفيف بايت، ثم يمكنك التحكم فيها على النظام اخترت بايت بها، وendian نيس وحدة المعالجة المركزية ينتهي فعليا حتى لا mattering.

وهذا هو أيضا مفيدة للغاية من حيث التعامل مع مشاكل المحاذاة. تفريغ الأساسية الخاصة بك قد يكون concievably الإشارات الصغيرة المحايدة في ذلك. وأنا أعلم أن من المستبعد جدا، لكنه قد يكون راجعا إلى الفساد أيضا. هذا هو مشكلة أخرى وتجنبها عن طريق معالجة الملف كما صفيف بايت.

ولقد استخدمت هذه الطريقة في تنفيذ jhead.

ويمكنك استخدام الشبكة القياسية bytswapping وظائف في APA / inet.h:

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong); // Host to network
uint16_t htons(uint16_t hostshort); // Host to network
uint32_t ntohl(uint32_t netlong); // Network to host
uint16_t ntohs(uint16_t netshort); // Network to host

وترتيب البايت شبكة كبيرة-endian. لذا، فإن هذه الوظائف تعني:

hton*: Host endian to big endian
ntoh*: Big endian to host endian

وآمل أن يساعد هذا.

ونلقي نظرة على رؤوس المقدمة النواة في / البيرة / وتشمل / لينكس / byteorder / مثل __cpu_to_be32 () و__be32_to_cpu ()

وتأخذ أيضا نظرة على ملف /usr/include/linux/types.h حيث يمكنك تحديد أنواع على النحو الكبير / Endian طفيف صحيحة واضحة صريحة، والتي تساعد كثيرا منذ سوف يتم الكشف عن أي عدم تطابق في وقت الترجمة.

لماذا تحتاج إلى API للقيام بذلك؟ ببساطة كتابة وظيفة الخاصة بك للاتصال htonl() (أو ما ينتج BE) ثم ببساطة عكس بايت. أن لا يبدو من الصعب جدا.

وشيء من هذا القبيل:

union {
    struct {
        unsigned char c0;
        unsigned char c1;
        unsigned char c2;
        unsigned char c3;
    } ch;
    uint32_t ui;
} u;
unsigned char t;

u.ui = htonl (hostlong);
t = u.ch.c0; u.ch.c0 = u.ch.c3 ; u.ch.c3 = t;
t = u.ch.c1; u.ch.c1 = u.ch.c2 ; u.ch.c2 = t;

وبالنظر إلى أن التحول endian-وفاق سطيف <لأ href = "http://www.ibm.com/developerworks/aix/library/au-endianc/index.html؟ca=drs-#N1028E" يختلط = "نوفولو noreferrer "> هو السهل ، وأنا دائما انتهى باستخدام تعليمات برمجية مخصصة من هذا القبيل، والحفاظ على قاعدة صارمة حول ما تمثيل يمكنني استخدامها في الرمز، والتعامل مع endianity في نقطة النهاية (المدخلات والمخرجات).

هل يمكن أن مجرد كتابة بنفسك (تستند هذه على الروتين أبل):

static inline uint16_t Swap16(uint16_t x)
{
    return ( (x << 8) | (x >> 8) );
}

static inline uint32_t Swap32(uint32_t x)
{
    return ( (((x ^ (x >> 16 | (x << 16))) & 0xff00ffff) >> 8) ^ (x >> 8 | data << 24) );
}

وبعد ذلك يمكنك تحديد وحدات الماكرو الشرطية:

#ifdef __BIG_ENDIAN__
# define htols(x) Swap16(x)
# define htoll(x) Swap32(x)
#else
# define htols(x) (x)
# define htoll(x) (x)
#endif

إذا كنت سعيدا مع رمز المجمع إنتل، يمكنك أن تفعل حتى هذا:

// Swap16 is unchanged

static inline uint32_t Swap32(uint32_t x)
{
    __asm__ ("bswap %0" : "+r" (x));
    return ( x );
}
#ifdef __i386__
static inline uint64_t Swap64(uint64_t x)
{
    __asm__ ("bswap  %%eax\n\t"
             "bswap  %%edx\n\t"
             "xchgl  %%eax, %%edx"
             : "+A" (x));
    return ( x );
}
#elif defined(__x86_64__)
static inline uint64_t Swap64( uint64_t x )
{
    __asm__ ("bswap  %0" : "+r" (x));
    return ( x );
}
#endif
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top