1

下面是一段获取 .NET 程序集构建时间的代码。笔记:

const int c_LinkerTimestampOffset = 8;

然后:

int secondsSince1970 = System.BitConverter.ToInt32(b, i + c_LinkerTimestampOffset);

此代码提取存储在程序集中的IMAGE_FILE_HEADER 结构TimeDateStamp的成员。结构定义如下:

typedef struct _IMAGE_FILE_HEADER {
    WORD  Machine;
    WORD  NumberOfSections;
    DWORD TimeDateStamp;
    DWORD PointerToSymbolTable;
    DWORD NumberOfSymbols;
    WORD  SizeOfOptionalHeader;
    WORD  Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

andWORD是两个字节,应该是两个字节对齐的。当我使用 Visual C++ 10 编译以下代码时:

IMAGE_FILE_HEADER header;
char* start = (char*)&header;
char* field = (char*)(&header.TimeDateStamp);
int diff = field - start;

diff等于4我个人的预期。

这是 C# 代码中的错误吗?为什么8使用偏移值?

4

3 回答 3

3

它用于跳过附加签名,因为i它包含 NT 标头的偏移量,而不是文件图像标头(请参阅正式的 PE 结构):

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature; //<- we need to skip this
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

所以实际总和是sizeof(WORD /* FileHeader.Machine */) + sizeof(WORD /* FileHeader.NumberOfSections */) + sizeof(DWORD /* Signature */)

底线,不是错误,只是跳过一些结构嵌套/内联的一些魔法。

于 2012-09-28T12:29:22.390 回答
0

DWORD 是一个 int 无符号值,4 个字节。

C# 代码不正确,它读取 8 个字节。我觉得应该是4。

int secondsSince1970 = System.BitConverter.ToInt32(b, i + c_LinkerTimestampOffset);

几天前我写了一个PE阅读器。我将其用于“图像文件头”:

public class IMAGE_FILE_HEADER 
{
     public UInt16 Machine;
     public UInt16 NumberOfSections;
     public UInt32 TimeDateStamp;
     public UInt32 PointerToSymbolTable;
     public UInt32 NumberOfSymbols;
     public UInt16 SizeOfOptionalHeader;
     public UInt16 Characteristics;
}
于 2012-09-28T12:10:04.543 回答
-1

您很可能会得到 8 字节的差异,因为您使用的是 64 位系统/目标平台,如果您使用的是 32 位,那将是您所期望的。

在 32 位系统上,DWORD 定义为 uint(32 位/4 字节),而在 64 位系统上,它定义为 ulong(64 位/8 字节)。

一个字本质上代表架构的地址大小。当它被创造出来时,一个 WORD 是 16 位,而一个 DWORD 是一个双字,32 位(4 个字节)。

有人会期望 DWORD 在 x86 系统上为 64 位/8 字节,但 MS 希望保留旧版支持,因此保留了旧定义:http: //msdn.microsoft.com/en-us/library/aa383751 (VS.85).aspx

于 2012-09-28T12:49:36.570 回答