Почему определение структуры, скопированное из winapi в мой код, не имеет такого поведения? - PullRequest
1 голос
/ 08 января 2020

Я пытаюсь прочитать IMAGE_DOS_HEADER модуля, используя определение этой структуры из winapi ящика.

Вот мой рабочий код:

let mut IDH: IMAGE_DOS_HEADER = uninitialized();
copy_nonoverlapping(library, (&mut IDH as *mut IMAGE_DOS_HEADER) as *mut c_void, size_of::<IMAGE_DOS_HEADER>());

Я понял, что winapi слишком велик, и я хотел, чтобы мой двоичный файл был меньше мегабайта, поэтому я объявил структуру IMAGE_DOS_HEADER самостоятельно:

#[derive(Copy, Clone)]
pub struct _IMAGE_DOS_HEADER{
    pub e_magic: u16,
    pub e_cblp: u16,
    pub e_cp: u16,
    pub e_crlc: u16,
    pub e_cparhdr: u16,
    pub e_minalloc: u16,
    pub e_maxalloc: u16,
    pub e_ss: u16,
    pub e_sp: u16,
    pub e_csum: u16,
    pub e_ip: u16,
    pub e_cs: u16,
    pub e_lfarlc: u16,
    pub e_ovno: u16,
    pub e_res: [u16; 4],
    pub e_oemid: u16,
    pub e_oeminfo: u16,
    pub e_res2: [u16; 10],
    pub e_lfanew: i32,
}

Когда я При этом все поля структуры получают странные значения (например: e_magic = 0x3).

Я решил преобразовать структуру в массив в обоих случаях, даже если они программно совпадают.

println!("{:?}", std::mem::transmute::<IMAGE_DOS_HEADER, [u8;0x40]>(IDH).to_vec());

Для них обоих напечатано:

[77, 90, 144, 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0]

Это действительно странно. Не должно быть никаких различий между значениями их полей. Затем я скопировал напечатанный массив и преобразовал его в свою структуру и проверил, все ли поля в порядке.

let dos: [u8;0x40] = [77, 90, 144, 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0];
println!("{}", std::mem::transmute::<[u8;0x40], _IMAGE_DOS_HEADER>(dos).e_magic);

Первое поле равно 3. У меня есть две структуры с одинаковыми полями и одинаковым размером (я подтвердил), я беру массив, преобразовываю его в эти структуры и получаю разные поля.

Как видите, есть 3 в дампе массива, но он не должен быть связан с первым полем структуры (e_magic), нет смысла, зачем он будет работать с другим?

Я думаю, я что-то не хватает, когда я инициализирую структуру, но что?

1 Ответ

4 голосов
/ 08 января 2020

Вы не скопировали то же определение, вы скопировали часть, которая показана в документации. Это (усеченное) фактическое определение :

STRUCT!{struct IMAGE_DOS_HEADER {
    e_magic: WORD,
    e_cblp: WORD,
    // ...
    e_res2: [WORD; 10],
    e_lfanew: LONG,
}}

Примечательно, что здесь используется макрос STRUCT , который определяет несколько черт, но, что более важно, отмечает тип как repr(C):

#[repr(C)] #[derive(Copy)] $(#[$attrs])*
pub struct $name {
    $(pub $field: $ftype,)+
}

Расположение структур Rust не указано, поэтому ваша структура имеет некоторые другие порядок и отступы по сравнению со структурой C и не будет работать.


Я понял, что winapi слишком велик, и я хотел, чтобы размер моего двоичного файла был меньше мегабайта, поэтому я объявил структуру IMAGE_DOS_HEADER самостоятельно

Это неверные рассуждения , Код из неиспользуемых библиотек удаляется из окончательного двоичного файла.

См. Также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...