/* 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;
}