Andiness sweep without ntohs

I am writing an ELF analyzer, but I am having problems with the correct conversion. I have functions for determining the conjunction of the analyzer and the limb of an object file.

Basically, there are four possible scenarios:

  • A large-end compiled analyzer prepares for a large endian object
    • nothing needs to be converted
  • Compiled large-end analyzer running in a small endian object
    • the byte order requires replacement, but ntohs / l () and htons / l () are null macros on the big end machine, so they will not change the byte order. This is problem
  • A small final compiled analyzer runs in a large endian object
    • the byte order must be replaced, so use htons () to replace the byte order
  • A small final compiled analyzer runs in a small endian object.
    • nothing needs to be converted

Is there a function that I can use to explicitly override bytes / change bytes, since ntohs / l () and htons / l () take into account the host endpoint and sometimes do not convert? Or do I need to find / write my own byte byte exchange function?

+8
c ++ endianness
source share
5 answers

Do I need to find / write my own byte byte exchange function?

Yes Yes. But to make it easy, I refer you to this question: How to convert big-endian and little-endian values ​​to C ++? , which gives a list of compilers specific byte-order swap functions, as well as some implementations of byte-swap functions.

+3
source share

I think it's worth reimbursing an article about a byte error written by Rob Pake (one of Go's authors).

If you do everything right - that is, you do not assume anything about your byte ordering of the platforms - then it will work. All you need to take care of is ELF files in Little Endian or Big Endian mode.

From the article:

Suppose your data stream has a 32-bit encoding with a small entiance. Here's how to extract it (assuming unsigned bytes):

i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24); 

If it's big-endian, here's how to extract it:

 i = (data[3]<<0) | (data[2]<<8) | (data[1]<<16) | (data[0]<<24); 

And just let the compiler worry about optimizing the heck from it.

+10
source share

On Linux, there are several conversion functions in endian.h that allow you to convert between arbitrary precision:

 uint16_t htobe16(uint16_t host_16bits); uint16_t htole16(uint16_t host_16bits); uint16_t be16toh(uint16_t big_endian_16bits); uint16_t le16toh(uint16_t little_endian_16bits); uint32_t htobe32(uint32_t host_32bits); uint32_t htole32(uint32_t host_32bits); uint32_t be32toh(uint32_t big_endian_32bits); uint32_t le32toh(uint32_t little_endian_32bits); uint64_t htobe64(uint64_t host_64bits); uint64_t htole64(uint64_t host_64bits); uint64_t be64toh(uint64_t big_endian_64bits); uint64_t le64toh(uint64_t little_endian_64bits); 

An edited, less reliable solution. You can use union to access bytes in any order. This is pretty handy:

 union { short number; char bytes[sizeof(number)]; }; 
+7
source share

Ntoh functions can vary between a large, rather than a large number of characters. Some systems are also β€œmedium”, where bytes are scrambled, and not just ordered one way or another.

In any case, if all you care about is big and small endian, then all you need to know is that the main and final object files are different. You will have your own function, which unconditionally changes the order of bytes, and you will call it or not, based on whether there is host_endianess()==objectfile_endianess() .

+1
source share

If I thought of a cross-platform solution that would work on Windows or Linux, I would write something like:

 #include <algorithm> // dataSize is the number of bytes to convert. char le[dataSize];// little-endian char be[dataSize];// big-endian // Fill contents in le here... std::reverse_copy(le, le + dataSize, be); 
0
source share

All Articles