diff options
author | Stefan Bucur <stefanb@zytor.com> | 2008-06-11 14:33:00 +0300 |
---|---|---|
committer | Stefan Bucur <stefan@stefan-ubumac.(none)> | 2009-03-15 10:02:13 +0200 |
commit | faad4e48cbd6e8f552a4c0edf1bdd177a8d375ce (patch) | |
tree | 63ee1bb84c8f19e6dacb2eae16e8dd7cf34204f0 | |
parent | ff98982feb408765bf644df3bb848ef0cacc63d2 (diff) | |
download | syslinux-elf-faad4e48cbd6e8f552a4c0edf1bdd177a8d375ce.tar.gz syslinux-elf-faad4e48cbd6e8f552a4c0edf1bdd177a8d375ce.tar.xz syslinux-elf-faad4e48cbd6e8f552a4c0edf1bdd177a8d375ce.zip |
Extracted symbol information from the ELF file.
-rw-r--r-- | elf/elf_module.c | 100 | ||||
-rw-r--r-- | elf/elf_module.h | 18 | ||||
-rw-r--r-- | elf/hello.c | 11 |
3 files changed, 83 insertions, 46 deletions
diff --git a/elf/elf_module.c b/elf/elf_module.c index 037b585e..22900b7a 100644 --- a/elf/elf_module.c +++ b/elf/elf_module.c @@ -62,24 +62,24 @@ static int load_image(struct elf_module *module) { strcpy(file_name, module->name); strcat(file_name, ".so"); - module->file_fd = open(file_name, O_RDONLY); + module->_file_fd = open(file_name, O_RDONLY); - if (module->file_fd < 0) { + if (module->_file_fd < 0) { perror("Could not open object file"); goto error; } - if (fstat(module->file_fd, &elf_stat) < 0) { + if (fstat(module->_file_fd, &elf_stat) < 0) { perror("Could not get file information"); goto error; } - module->file_size = elf_stat.st_size; + module->_file_size = elf_stat.st_size; - module->file_image = mmap(NULL, module->file_size, PROT_READ, MAP_PRIVATE, - module->file_fd, 0); + module->_file_image = mmap(NULL, module->_file_size, PROT_READ, MAP_PRIVATE, + module->_file_fd, 0); - if (module->file_image == NULL) { + if (module->_file_image == NULL) { perror("Could not map the file into memory"); goto error; } @@ -87,25 +87,25 @@ static int load_image(struct elf_module *module) { return 0; error: - if (module->file_image != NULL) { - munmap(module->file_image, module->file_size); - module->file_image = NULL; + if (module->_file_image != NULL) { + munmap(module->_file_image, module->_file_size); + module->_file_image = NULL; } - if (module->file_fd > 0) { - close(module->file_fd); - module->file_fd = 0; + if (module->_file_fd > 0) { + close(module->_file_fd); + module->_file_fd = 0; } return -1; } static int unload_image(struct elf_module *module) { - munmap(module->file_image, module->file_size); - module->file_image = NULL; + munmap(module->_file_image, module->_file_size); + module->_file_image = NULL; - close(module->file_fd); - module->file_fd = 0; + close(module->_file_fd); + module->_file_fd = 0; return 0; } @@ -148,7 +148,7 @@ struct elf_module *module_alloc(const char *name) { // Performs verifications on ELF header to assure that the open file is a // valid SYSLINUX ELF module. static int check_header(struct elf_module *module) { - Elf32_Ehdr *elf_hdr = elf_get_header(module->file_image); + Elf32_Ehdr *elf_hdr = elf_get_header(module->_file_image); // Check the header magic if (elf_hdr->e_ident[EI_MAG0] != ELFMAG0 || @@ -197,7 +197,7 @@ static int check_header(struct elf_module *module) { static int load_segments(struct elf_module *module) { int i; - Elf32_Ehdr *elf_hdr = elf_get_header(module->file_image); + Elf32_Ehdr *elf_hdr = elf_get_header(module->_file_image); Elf32_Phdr *cr_pht; Elf32_Addr min_addr = 0x00000000; // Min. ELF vaddr @@ -208,7 +208,7 @@ static int load_segments(struct elf_module *module) { // Compute the memory needings of the module for (i=0; i < elf_hdr->e_phnum; i++) { - cr_pht = elf_get_ph(module->file_image, i); + cr_pht = elf_get_ph(module->_file_image, i); if (cr_pht->p_type == PT_LOAD) { if (i == 0) { @@ -252,12 +252,12 @@ static int load_segments(struct elf_module *module) { memset(module->module_addr, 0, module->module_size); for (i = 0; i < elf_hdr->e_phnum; i++) { - cr_pht = elf_get_ph(module->file_image, i); + cr_pht = elf_get_ph(module->_file_image, i); if (cr_pht->p_type == PT_LOAD) { // Copy the segment at its destination memcpy((void*)(module->base_addr + cr_pht->p_vaddr), - module->file_image + cr_pht->p_offset, + module->_file_image + cr_pht->p_offset, cr_pht->p_filesz); printf("Loadable segment of size 0x%08x copied from vaddr 0x%08x at 0x%08x\n", @@ -274,16 +274,15 @@ static int load_segments(struct elf_module *module) { return 0; } - -static int resolve_symbols(struct elf_module *module) { +static int prepare_dynlinking(struct elf_module *module) { int i; - Elf32_Ehdr *elf_hdr = elf_get_header(module->file_image); + Elf32_Ehdr *elf_hdr = elf_get_header(module->_file_image); Elf32_Phdr *dyn_ph; // The program header for the dynamic section Elf32_Dyn *dyn_entry; // The table of dynamic linking information for (i=0; i < elf_hdr->e_phnum; i++) { - dyn_ph = elf_get_ph(module->file_image, i); + dyn_ph = elf_get_ph(module->_file_image, i); if (dyn_ph->p_type == PT_DYNAMIC) break; @@ -296,34 +295,56 @@ static int resolve_symbols(struct elf_module *module) { return -1; } - dyn_entry = (Elf32_Dyn*)(module->file_image + dyn_ph->p_offset); + module->_dyn_info = (Elf32_Dyn*)(module->_file_image + dyn_ph->p_offset); + dyn_entry = module->_dyn_info; while (dyn_entry->d_tag != DT_NULL) { switch (dyn_entry->d_tag) { case DT_NEEDED: // TODO: Manage dependencies here break; - case DT_PLTRELSZ: - - case DT_PLTGOT: - case DT_HASH: + module->hash_table = (Elf32_Word*)(dyn_entry->d_un.d_ptr + module->base_addr); + break; case DT_GNU_HASH: // TODO: Add support for this one, too (50% faster) - + module->ghash_table = (Elf32_Word*)(dyn_entry->d_un.d_ptr + module->base_addr); + break; case DT_STRTAB: - + module->str_table = (char*)(dyn_entry->d_un.d_ptr + module->base_addr); + break; case DT_SYMTAB: - + module->sym_table = (void*)(dyn_entry->d_un.d_ptr + module->base_addr); + break; + case DT_STRSZ: + module->strtable_size = dyn_entry->d_un.d_val; + break; + case DT_SYMENT: + module->syment_size = dyn_entry->d_un.d_val; + break; + } + + dyn_entry++; + } + + + return 0; +} + +static int resolve_symbols(struct elf_module *module) { + Elf32_Dyn *dyn_entry = module->_dyn_info; + + while (dyn_entry->d_tag != DT_NULL) { + switch(dyn_entry->d_tag) { case DT_RELA: case DT_RELASZ: case DT_RELAENT: - case DT_STRSZ: + case DT_PLTRELSZ: - case DT_SYMENT: + case DT_PLTGOT: // The first entry in the GOT case DT_INIT: @@ -340,15 +361,11 @@ static int resolve_symbols(struct elf_module *module) { case DT_JMPREL: printf("Recognized DYN tag: %d\n", dyn_entry->d_tag); break; - default: - printf("Custom DYN tag: 0x%08x\n", dyn_entry->d_tag); - break; } dyn_entry++; } - return 0; } @@ -372,12 +389,13 @@ int module_load(struct elf_module *module) { CHECKED(res, check_header(module), error); // Obtain the ELF header - elf_hdr = elf_get_header(module->file_image); + elf_hdr = elf_get_header(module->_file_image); // DEBUG print_elf_ehdr(elf_hdr); CHECKED(res, load_segments(module), error); + CHECKED(res, prepare_dynlinking(module), error); CHECKED(res, resolve_symbols(module), error); diff --git a/elf/elf_module.h b/elf/elf_module.h index 6074b559..46bbfd3b 100644 --- a/elf/elf_module.h +++ b/elf/elf_module.h @@ -27,16 +27,28 @@ struct elf_module { module_init_func init_func; // The initialization entry point module_exit_func exit_func; // The module finalization code - void *file_image; // The image of the module file in memory - uint32_t file_size; // The size of the module file void *module_addr; // The module location in the memory Elf32_Addr base_addr; // The base address of the module Elf32_Word module_size; // The module size in memory + Elf32_Word *hash_table; // The symbol hash table + Elf32_Word *ghash_table; // The GNU style hash table + char *str_table; // The string table + void *sym_table; // The symbol table + + Elf32_Word strtable_size; // The size of the string table + Elf32_Word syment_size; // The size of a symbol entry + + + // Transient - Data available while the module is loading + void *_file_image; // The image of the module file in memory + uint32_t _file_size; // The size of the module file + Elf32_Dyn *_dyn_info; // Dynamic loading information + // Information for modules loaded in user space #ifdef ELF_USERSPACE_TEST - int file_fd; // The file descriptor of the open file + int _file_fd; // The file descriptor of the open file #endif }; diff --git a/elf/hello.c b/elf/hello.c index d7b46c04..0ab84de4 100644 --- a/elf/hello.c +++ b/elf/hello.c @@ -3,11 +3,18 @@ // TODO: Define some macros that would put the initialization and termination // functions in a separate section (suggestion: .init and .fini) +// Undefined symbol +extern int undef_symbol; + +// Undefined function +extern void undef_func(int param); + int hello_init() { - // Do nothing + undef_symbol++; + return 0; } void hello_exit() { - // Do nothing + undef_func(undef_symbol); } |