/* Resolution des references symboliques. */ /* Copyright (C) 2008 Emmanuel Varoquaux This file is part of XOS. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "resolve.h" #include "vars.h" #include "object_info.h" #include /* Cherche un symbole de nom symbol_name dans l'objet object_info. * symbol_name doit etre non vide. */ static const Elf32_Sym *lookup_symbol(const char *symbol_name, const struct object_info_struct *object_info) { const char *string_table; const Elf32_Sym *symbol_table; const Elf32_Word *symbol_hash_table; int nbuckets; const Elf32_Word *bucket_array; const Elf32_Word *chain_array; register int idx; string_table = object_info->dynamic_data.string_table; symbol_table = object_info->dynamic_data.symbol_table; symbol_hash_table = object_info->dynamic_data.symbol_hash_table; nbuckets = symbol_hash_table[0]; if (nbuckets == 0) return NULL; bucket_array = symbol_hash_table + 2; chain_array = bucket_array + nbuckets; idx = bucket_array[elf_hash((const unsigned char *)symbol_name) % nbuckets]; while (1) { if (!strcmp(symbol_name, string_table + symbol_table[idx].st_name)) return &symbol_table[idx]; if (chain_array[idx] == STN_UNDEF) return NULL; idx = chain_array[idx]; } } /* Cherche un symbole defini de nom symbol_name dans l'objet object_info. * symbol_name doit etre non vide. */ static const Elf32_Sym *search_symbol_definition(const char *symbol_name, struct object_info_struct *object_info) { const Elf32_Sym *symbol; if (!(symbol = lookup_symbol(symbol_name, object_info))) return NULL; if (symbol->st_shndx != SHN_UNDEF) return symbol; if (object_info->type == OI_EXEC && ELF32_ST_TYPE(symbol->st_info) == STT_FUNC && symbol->st_value) return symbol; return NULL; } int resolve_symbol(struct object_info_struct *object_info, const Elf32_Sym *symbol, int flags, struct object_info_struct **found_object_info, const Elf32_Sym **found_symbol) { const char *symbol_name; struct object_info_struct *object_info_1; if (!symbol->st_name) return 0; symbol_name = object_info->dynamic_data.string_table + symbol->st_name; /* DT_SYMBOLIC : recherche d'abord dans l'objet partage. */ if (object_info->type != OI_EXEC && object_info->dynamic_data.symbolic) if ((*found_symbol = search_symbol_definition(symbol_name, object_info))) { *found_object_info = object_info; return 1; } /* Recherche d'abord dans l'executable. */ if (!(flags & RF_NOEXEC)) if ((*found_symbol = search_symbol_definition(symbol_name, &executable_info))) { *found_object_info = &executable_info; return 1; } /* Recherche dans les objets partages. */ for (object_info_1 = shared_object_info_list.first; object_info_1; object_info_1 = object_info_1->next) if ((*found_symbol = search_symbol_definition(symbol_name, object_info_1))) { *found_object_info = object_info_1; return 1; } /* Reference symbolique non trouvee. */ /* Symbole faible ? */ if (ELF32_ST_BIND(symbol->st_info) == STB_WEAK) { *found_symbol = NULL; *found_object_info = NULL; return 1; } /* Echec de la resolution. */ return 0; }