mirror of
https://github.com/0Nera/BMOSP.git
synced 2024-11-22 08:31:23 +03:00
Добавлен разбор ELF файлов
This commit is contained in:
parent
e7233a7b4c
commit
40c1604109
108
include/mod.h
108
include/mod.h
@ -7,37 +7,109 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <log.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys.h>
|
||||
|
||||
#ifndef MOD_H
|
||||
#define MOD_H
|
||||
|
||||
// Максимальное количество модулей 16. Позже перепишем на динамический массив,
|
||||
// сейчас для прототипа это не так важно
|
||||
#define MOD_MAX 16
|
||||
#define EI_MAG0 0
|
||||
#define ELFMAG0 0x7f
|
||||
#define EI_MAG1 1
|
||||
#define ELFMAG1 'E'
|
||||
#define EI_MAG2 2
|
||||
#define ELFMAG2 'L'
|
||||
#define EI_MAG3 3
|
||||
#define ELFMAG3 'F'
|
||||
#define SHT_SYMTAB 2
|
||||
|
||||
typedef uint64_t elf64_addr_t; // Адрес
|
||||
typedef uint64_t elf64_offset_t; // Смещение
|
||||
typedef uint64_t elf64_xword_t; // Целочисленное длинное слово без знака
|
||||
typedef uint64_t elf64_sxword_t; // Целочисленное длинное слово с знаком
|
||||
typedef uint32_t elf64_word_t; // Целочисленное слово без знака
|
||||
typedef uint32_t elf64_sword_t; // Целочисленное слово с знаком
|
||||
typedef uint16_t elf64_half_t; // Среднее целое число без знака
|
||||
typedef uint8_t elf64_small_t; // Малое целое число без знака
|
||||
|
||||
// Структуры соответствующие ELF заголовкам
|
||||
typedef struct {
|
||||
unsigned char e_ident[16];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
uint32_t e_version;
|
||||
uint64_t e_entry;
|
||||
uint64_t e_phoff;
|
||||
uint64_t e_shoff;
|
||||
uint32_t e_flags;
|
||||
uint16_t e_ehsize;
|
||||
uint16_t e_phentsize;
|
||||
uint16_t e_phnum;
|
||||
uint16_t e_shentsize;
|
||||
uint16_t e_shnum;
|
||||
uint16_t e_shstrndx;
|
||||
elf64_small_t e_ident[16]; // Идентификация ELF
|
||||
elf64_half_t e_type; // Тип объектного файла
|
||||
elf64_half_t e_machine; // Тип компьютера
|
||||
elf64_word_t e_version; // Версия объектного файла
|
||||
elf64_addr_t e_entry; // Адрес точки входа
|
||||
elf64_offset_t e_phoff; // Смещение заголовка программы
|
||||
elf64_offset_t e_shoff; // Смещение заголовка раздела
|
||||
elf64_word_t e_flags; // Флаги, зависящие от процессора
|
||||
elf64_half_t e_ehsize; // Размер заголовка ELF
|
||||
elf64_half_t e_phentsize; // Размер записи заголовка программы
|
||||
elf64_half_t e_phnum; // Количество записей в заголовке программы
|
||||
elf64_half_t e_shentsize; // Размер записи в заголовке раздела
|
||||
elf64_half_t e_shnum; // Количество записей в заголовке раздела
|
||||
elf64_half_t e_shstrndx; // Строковый табличный индекс названия раздела
|
||||
} elf64_header_t;
|
||||
|
||||
typedef struct {
|
||||
elf64_word_t sh_name; // Название раздела
|
||||
elf64_word_t sh_type; // Тип раздела
|
||||
elf64_xword_t sh_flags; // Атрибуты раздела
|
||||
elf64_addr_t sh_addr; // Виртуальный адрес в памяти
|
||||
elf64_offset_t sh_offset; // Смещение в файле
|
||||
elf64_xword_t sh_size; // Размер раздела
|
||||
elf64_word_t sh_link; // Ссылка на другой раздел
|
||||
elf64_word_t sh_info; // Дополнительная информация
|
||||
elf64_xword_t sh_addralign; // Граница выравнивания адреса
|
||||
elf64_xword_t sh_entsize; // Размер записей, если в разделе есть таблица
|
||||
} elf64_section_header_t;
|
||||
|
||||
typedef struct {
|
||||
elf64_addr_t r_offset; // Адрес ссылки
|
||||
elf64_xword_t r_info; // Индекс символа и тип перемещения
|
||||
} elf64_rel_t;
|
||||
|
||||
typedef struct {
|
||||
elf64_addr_t r_offset; // Адрес ссылки
|
||||
elf64_xword_t r_info; // Индекс символа и тип перемещения
|
||||
elf64_sxword_t r_addend; // Постоянная часть выражения
|
||||
} elf64_rela_t;
|
||||
|
||||
typedef struct {
|
||||
elf64_word_t p_type; // Тип сегмента
|
||||
elf64_word_t p_flags; // Атрибуты сегмента
|
||||
elf64_offset_t p_offset; // Смещение в файле
|
||||
elf64_addr_t p_vaddr; // Виртуальный адрес в памяти
|
||||
elf64_addr_t p_paddr; // Зарезервирован
|
||||
elf64_xword_t p_filesz; // Размер сегмента в файле
|
||||
elf64_xword_t p_memsz; // Размер сегмента в памяти
|
||||
elf64_xword_t p_align; // Выравнивание сегмента
|
||||
} elf64_phdr_t;
|
||||
|
||||
typedef struct {
|
||||
elf64_word_t st_name; // Название символа
|
||||
elf64_small_t st_info; // Тип и атрибуты привязки
|
||||
elf64_small_t st_other; // Зарезервировано
|
||||
elf64_half_t st_shndx; // Индекс таблицы разделов
|
||||
elf64_addr_t st_value; // Значение символа
|
||||
elf64_xword_t st_size; // Размер объекта (например, общий)
|
||||
} elf64_sym_t;
|
||||
|
||||
typedef struct {
|
||||
elf64_sxword_t d_tag; // Тип динамического элемента
|
||||
union {
|
||||
elf64_xword_t d_val; // Значение динамического элемента
|
||||
elf64_addr_t d_ptr; // Указатель динамического элемента
|
||||
} d_un;
|
||||
} elf64_dyn_t;
|
||||
|
||||
void mod_init( );
|
||||
void mod_after_init( );
|
||||
void mod_list_show( );
|
||||
module_info_t *mod_find(char *tag);
|
||||
module_info_t *mod_list_get(uint64_t *count);
|
||||
|
||||
void *elf_entry(void *module_bin);
|
||||
void *elf_parse(elf64_header_t *head);
|
||||
|
||||
#endif // mod.h
|
@ -1,3 +1,3 @@
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_BUILD 57
|
||||
#define VERSION_BUILD 58
|
||||
|
116
kernel/elf.c
Normal file
116
kernel/elf.c
Normal file
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* elf.c
|
||||
* Функции работы с ELF64
|
||||
*
|
||||
* Инструменты для парсинга и анализа ELF файлов
|
||||
*
|
||||
*/
|
||||
|
||||
#include <mod.h>
|
||||
#include <stdint.h>
|
||||
|
||||
elf64_header_t *elf64_get_header(void *data) {
|
||||
return (elf64_header_t *)(data);
|
||||
}
|
||||
|
||||
static inline elf64_section_header_t *elf64_sheader(elf64_header_t *hdr) {
|
||||
return (elf64_section_header_t *)((elf64_addr_t)hdr + hdr->e_shoff);
|
||||
}
|
||||
|
||||
static inline elf64_section_header_t *elf64_section(elf64_header_t *hdr, elf64_offset_t idx) {
|
||||
return &elf64_sheader(hdr)[idx];
|
||||
}
|
||||
|
||||
static inline char *elf64_str_table(elf64_header_t *hdr) {
|
||||
if (hdr->e_shstrndx == 0x0) return NULL;
|
||||
return (char *)hdr + elf64_section(hdr, hdr->e_shstrndx)->sh_offset;
|
||||
}
|
||||
|
||||
static inline char *elf64_lookup_string(elf64_header_t *hdr, elf64_offset_t offset) {
|
||||
char *strtab = elf64_str_table(hdr);
|
||||
if (strtab == NULL) return NULL;
|
||||
return strtab + offset;
|
||||
}
|
||||
|
||||
static elf64_sym_t *elf64_get_symval(elf64_header_t *hdr, elf64_offset_t table, elf64_offset_t idx) {
|
||||
if (table == 0 || idx == 0) return 0;
|
||||
elf64_section_header_t *symtab = elf64_section(hdr, table);
|
||||
|
||||
uint32_t symtab_entries = symtab->sh_size / symtab->sh_entsize;
|
||||
if (idx >= symtab_entries) {
|
||||
LOG("Индекс символа вне допустимых пределов (%u:%u).\n", table, idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uintptr_t symaddr = (uint64_t)hdr + symtab->sh_offset;
|
||||
return (elf64_sym_t *)&((elf64_sym_t *)symaddr)[idx];
|
||||
}
|
||||
|
||||
unsigned long elf64_hash(unsigned char *name) {
|
||||
unsigned long h = 0, g;
|
||||
// Вычисление хэша
|
||||
while (*name) {
|
||||
h = (h << 4) + *name++;
|
||||
// Проверка на overflow
|
||||
if (g = h & 0xf0000000) h ^= g >> 24;
|
||||
// Ограничение хэша
|
||||
h &= 0xffffffff;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
// Получение адреса точки входа
|
||||
void *elf_entry(void *module_bin) {
|
||||
// Приводим заголовок ELF файла к типу elf64_header_t
|
||||
elf64_header_t *elf_header = (elf64_header_t *)module_bin;
|
||||
|
||||
LOG("(uint64_t)elf_header->e_entry = 0x%x, тип = %u\n", (uint64_t)elf_header->e_entry, elf_header->e_type);
|
||||
|
||||
if (elf_header->e_type != 2) {
|
||||
LOG("\t\tОшибка! Модуль неправильно собран!\n");
|
||||
for (;;) { asm volatile("pause"); }
|
||||
}
|
||||
elf_parse((elf64_header_t *)module_bin);
|
||||
|
||||
// Возвращаем указатель на точку входа
|
||||
return (void *)((uint64_t)elf_header->e_entry + (uint64_t)module_bin);
|
||||
}
|
||||
|
||||
void *elf_parse(elf64_header_t *head) {
|
||||
elf64_section_header_t *symtab = NULL;
|
||||
|
||||
if (head->e_ident[0] != ELFMAG0 || head->e_ident[1] != ELFMAG1 || head->e_ident[2] != ELFMAG2 ||
|
||||
head->e_ident[3] != ELFMAG3) {
|
||||
LOG("Ошибка: Неправильный формат!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG("Точка входа: 0x%x\n", head->e_entry);
|
||||
|
||||
elf64_section_header_t *symtab_section = NULL;
|
||||
char *string_table = NULL;
|
||||
for (int i = 0; i < head->e_shnum; i++) {
|
||||
elf64_section_header_t *shdr = elf64_section(head, i);
|
||||
if (shdr->sh_type == SHT_SYMTAB) {
|
||||
symtab_section = shdr;
|
||||
elf64_section_header_t *strtab_section = elf64_section(head, shdr->sh_link);
|
||||
string_table = (char *)head + strtab_section->sh_offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (symtab_section && string_table) {
|
||||
LOG("\nТаблица символов:\n");
|
||||
LOG("%s %s %s %s\n", "Индекс", "Значение", "Размер", "Наименование");
|
||||
|
||||
int num_symbols = symtab_section->sh_size / symtab_section->sh_entsize;
|
||||
for (int i = 0; i < num_symbols; i++) {
|
||||
elf64_sym_t *sym = elf64_get_symval(head, symtab_section - elf64_sheader(head), i);
|
||||
if (sym) { LOG("%6u %8x %6x %s\n", i, sym->st_value, sym->st_size, string_table + sym->st_name); }
|
||||
}
|
||||
} else {
|
||||
LOG("Таблица символов не найдена!\n");
|
||||
}
|
||||
|
||||
return (void *)0;
|
||||
}
|
19
kernel/mod.c
19
kernel/mod.c
@ -29,22 +29,6 @@ static env_t main_env;
|
||||
void *bootpng_ptr;
|
||||
uint64_t bootpng_size;
|
||||
|
||||
// Получение адреса точки входа
|
||||
static void *elf_entry(elf64_header_t *module_bin) {
|
||||
// Приводим заголовок ELF файла к типу elf64_header_t
|
||||
elf64_header_t *elf_header = (elf64_header_t *)module_bin;
|
||||
|
||||
LOG("(uint64_t)elf_header->e_entry = 0x%x, тип = %u\n", (uint64_t)elf_header->e_entry, elf_header->e_type);
|
||||
|
||||
if (elf_header->e_type != 2) {
|
||||
LOG("\t\tОшибка! Модуль неправильно собран!\n");
|
||||
for (;;) { asm volatile("pause"); }
|
||||
}
|
||||
|
||||
// Возвращаем указатель на точку входа
|
||||
return (void *)((uint64_t)elf_header->e_entry + (uint64_t)module_bin);
|
||||
}
|
||||
|
||||
// Вывод списка модулей в отладчик
|
||||
void mod_list_show( ) {
|
||||
for (uint64_t i = 0; i < modules_count; i++) {
|
||||
@ -133,8 +117,7 @@ void mod_init( ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
module_info_t (*module_init)(env_t *env) =
|
||||
(module_info_t(*)(env_t * env)) elf_entry((elf64_header_t *)module_ptr->address);
|
||||
module_info_t (*module_init)(env_t *env) = (module_info_t(*)(env_t * env)) elf_entry(module_ptr->address);
|
||||
|
||||
// LOG("\t->Точка входа: 0x%x\n", module_init);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user