Почему я не могу читать файлы Big Endian ELF так же, как файлы Little Endian в C ++?

По сути, я делаю что-то похожее на https://wiki.osdev.org/ELF_Tutorial, где я загружаю данные в структуры и читаю различные секции по их смещениям. Хост имеет прямой порядок байтов, и я пытаюсь проанализировать файлы, которые были скомпилированы для цели с прямым порядком байтов. Я попытался сделать ту же последовательность кода с этими файлами с прямым порядком байтов, что и с файлами с прямым порядком байтов, но при попытке доступа к разделам в коде произошел сбой.

int fd = open(filename, O_RDONLY);
char *header_start = (char *)mmap(0, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
Elf32_Ehdr* elf_ehdr = (Elf32_Ehdr *)header_start;
Elf32_Shdr* elf_shdrs = (Elf32_Shdr *)((int)header_start + elf_ehdr->e_shoff);
Elf32_Shdr* sh_strtab = &elf_shdrs[elf_ehdr->e_shstrndx];
// code segfaults here when trying to access sh_strtab->sh_offset for big endian
// files, but works just fine for little endian files

Почему код не выполняется для файлов с прямым порядком байтов?

-2

Решение

В большом файле байтов elf_ehdr->e_shoff будет большим порядковым числом, и порядок байтов должен быть соблюден.

Скажем, мы имеем дело с 32 битами и e_shoff хорошее небольшое число, например 64. В старом порядке он будет записан в файле как 0x00000040. Но вы читаете этот файл на процессоре с прямым порядком байтов, поэтому 0x00000040 считывается из файла как двоичный двоичный объект и будет интерпретироваться процессором как 1073741824.

Elf32_Shdr* elf_shdrs = (Elf32_Shdr *)((int)header_start + elf_ehdr->e_shoff);

решает в

Elf32_Shdr* elf_shdrs = (Elf32_Shdr *)((int)header_start + 1073741824);

не

Elf32_Shdr* elf_shdrs = (Elf32_Shdr *)((int)header_start + 64);

и собирается пропустить цель с большим отрывом. Попытка получить доступ к членам в результате elf_shdrs бродит в неопределенном поведении.

Быстрое исправление взлома

Elf32_Shdr* elf_shdrs = (Elf32_Shdr *)(header_start + ResolveEndian(elf_ehdr->e_shoff));

где ResolveEndian представляет собой серию перегруженных функций, которые либо абсолютно ничего не делают, потому что порядковый номер файла совпадает с порядковым порядком в системе или меняет порядок байтов. Для многих примеров того, как это сделать, см. Как я могу преобразовать между значениями с прямым и младшим порядком байтов в C ++?

Более длинное исправление не будет использовать файлы, отображенные в памяти, а вместо этого десериализовать файл принимая во внимание различия в размерах переменных (и результирующие различия в смещениях) между 32- и 64-битными программами, а также порядок байтов. Это приведет к созданию более надежного и переносимого синтаксического анализатора, который всегда будет работать независимо от исходного ELF и реализации компилятора, используемой для построения синтаксического анализатора.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]