Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Supporting byte ordering in Linux user space

I'm writing a program on Linux in C to analyze core files produced from an embedded system. The core files might be little endian (ARM) or big endian (MIPS), and the program to analyze them might be running on a little endian host (x86) or big endian (PowerPC).

By looking at the headers I know whether the core is LE or BE. I'd rather my program not need to know whether the host it runs on is little or big endian, I'd like to use an API to handle it for me. If there is no better option, I guess I'll start relying on #ifdef __BIG_ENDIAN__.

In the Linux kernel we have cpu_to_le32 et al to convert from native byte ordering to little endian, etc. In user space there is htonl et al, which convert from native to big endian but no equivalent for native to little endian that I can find.

Can anyone suggest a suitable API for user space?

Edit: Just to be clear, I'm looking for an API which already knows whether my CPU is big or little endian and swaps byes accordingly. I don't want to have to litter my code with #ifdefs for this. I'm not just looking for code snippets to swap bytes; thank you for those, but that wasn't the point.

like image 547
DGentry Avatar asked Nov 27 '22 02:11

DGentry


2 Answers

#include <arpa/inet.h> is nice and portable, but only guarantees {ntoh,hton}{s,l}. If you need conversions on 64-bit values, or endian flipping on big-endian (where ntoh and hton do nothing), it won't be enough.

On Linux (glibc), #include <endian.h> provides the following, defined as appropriate for the current machine.

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

On *BSD, #include <sys/endian.h> provides these same macros.

like image 194
ephemient Avatar answered Dec 16 '22 04:12

ephemient


If you have access to the neon coprocessor and the memory is contiguous (example a video frame) you could execute swap16 on the frame using the q registers (128bytes) in this way; of course, you have to watch for alignment issues

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"
        );
}
like image 24
Jay Ram Avatar answered Dec 16 '22 02:12

Jay Ram