2012-04-26 37 views
8

我正在写一个ELF分析器,但我有一些麻烦,正确地转换字节顺序。我有函数来确定分析器的字节顺序和目标文件的字节顺序。字节替换没有ntohs

基本上有四种可能:

  1. 在大端对象文件大端编译分析仪运行
    • 没有什么需要转换
  2. 大端编译分析仪运行在一个小端文件目录文件
    • 字节顺序需要交换,但是ntohs/l()和htons/l()都是空的宏o n是一个大型机器,所以它们不会交换字节顺序。 这就是问题
  3. 在大端对象文件
    • 的字节顺序需要换一个小尾数编译分析仪运行,所以用htons()来交换字节顺序
  4. 一个小端编译分析器运行在一个小端文件上。
    • 没有什么需要转换

有没有我可以用一个函数来显式地调换字节顺序/更改端,因为还有ntohs/L()和htons/L()把主机的字节顺序考虑有时不转换?或者我需要找到/写我自己的交换字节顺序功能?

回答

7

在Linux中there are several conversion functionsendian.h,允许任意字节序之间的转换:

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); 

编辑,不可靠的解决方案。您可以使用union以任何顺序访问字节。这是很方便的:

union { 
    short number; 
    char bytes[sizeof(number)]; 
}; 
+0

虽然C++在技术上未定义的行为。 – bames53 2012-04-26 21:12:51

+0

但是,我们如何知道正确的顺序? – 2012-04-26 21:13:04

+0

@BoPersson OP知道,当他想交换字节。我编辑了我的答案以公开更合适的解决方案。 – 2012-04-26 21:24:59

1

ntoh函数可以在大小端之间进行切换。一些系统也是'中端',字节被加密,而不是单纯地按顺序排列。无论如何,如果你只关心大小端,那么你需要知道的只是主机和目标文件的大小不同。你会有自己的函数,无条件地交换字节顺序,你会根据是否host_endianess()==objectfile_endianess()来调用它。

0

如果我会考虑一个跨平台的解决方案,将在Windows或Linux的工作,我会写这样的东西:

#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); 
10

我认为这是值得在这里养The Byte Order Fallacy文章,由罗布派克(一个Go的作者)。

如果你做的事情是正确的 - 即你不要假设任何关于你的平台字节顺序 - 那么它就会工作。所有你需要关心的是ELF格式文件是否在Little EndianBig Endian模式下。

从文章:

比方说,你的数据流具有小端编码的32位整数。以下是如何提取它(假设无符号字节):

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

如果是大端,这里是如何将其解压:

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

,只是让有关的编译器忧优化它。

+0

如果您首先使用单词开头,AFAIK编译器将只使用优化的字节顺序交换。 – 2017-02-08 14:12:42

+0

@AndrewDunn:很可能,但像往常一样,测量两次,优化一次。 – 2017-02-08 14:23:16