/* OpenIDA - Outil d'analyse de fichiers binaires * symbol.c - gestion des symboles d'un ELF * * Copyright (C) 2008 Cyrille Bagard * * This file is part of OpenIDA. * * OpenIDA 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. * * OpenIDA 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 Foobar. If not, see . */ #include "symbol.h" #include #include #include #include "elf-int.h" #include "section.h" /* Charge en mémoire la liste humaine des symboles (32 bits). */ bool load_elf_symbol_table_32(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *); /* Charge en mémoire la liste humaine des symboles (64 bits). */ bool load_elf_symbol_table_64(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *); /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * * * Description : Charge en mémoire la liste humaine des symboles. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool load_elf_symbols(elf_format *format) { bool result; /* Bilan à retourner */ off_t sym_start; /* Début de section */ off_t sym_size; /* Taille de section */ off_t str_start; /* Début de section */ off_t str_size; /* Taille de section */ result = find_elf_section(format, ".symtab", &sym_start, &sym_size, NULL); result &= find_elf_section(format, ".strtab", &str_start, &str_size, NULL); if (result) { result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_start); } return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * sym_start = début de la zone à traiter. * * sym_size = taille de la zone à traiter. * * str_start = début de la zone de chaîne de caractères. * * str_size = taille de la zone de chaînes de caractères. * * * * Description : Charge en mémoire la liste humaine des symboles (32 bits). * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool load_elf_symbol_table_32(elf_format *format, const off_t *sym_start, const off_t *sym_size, const off_t *str_start, const off_t *str_size) { off_t iter; /* Boucle de parcours */ Elf32_Sym symbol; /* Symbole ELF lu */ if (*sym_size % sizeof(Elf32_Sym) != 0) return false; for (iter = *sym_start; iter < (*sym_start + *sym_size); iter += sizeof(Elf32_Sym)) { memcpy(&symbol, &EXE_FORMAT(format)->content[iter], sizeof(Elf32_Sym)); if (!(ELF32_ST_TYPE(symbol.st_info) == STT_FUNC || (ELF32_ST_TYPE(symbol.st_info) == STT_NOTYPE && ELF32_ST_BIND(symbol.st_info) == STB_GLOBAL))) continue; if (symbol.st_value == 0) continue; /* Sécurité anti-débordements */ if (symbol.st_name >= *str_size) continue; /* Si le symbole possède un nom... */ if (strlen(&EXE_FORMAT(format)->content[*str_start + symbol.st_name]) > 0) { format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol)); format->symbols[format->sym_count - 1].name = &EXE_FORMAT(format)->content[*str_start + symbol.st_name]; format->symbols[format->sym_count - 1].address = symbol.st_value; } } return true; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * sym_start = début de la zone à traiter. * * sym_size = taille de la zone à traiter. * * str_start = début de la zone de chaîne de caractères. * * str_size = taille de la zone de chaînes de caractères. * * * * Description : Charge en mémoire la liste humaine des symboles (64 bits). * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool load_elf_symbol_table_64(elf_format *format, const off_t *sym_start, const off_t *sym_size, const off_t *str_start, const off_t *str_size) { off_t iter; /* Boucle de parcours */ Elf64_Sym symbol; /* Symbole ELF lu */ if (*sym_size % sizeof(Elf64_Sym) != 0) return false; for (iter = *sym_start; iter < (*sym_start + *sym_size); iter += sizeof(Elf64_Sym)) { memcpy(&symbol, &EXE_FORMAT(format)->content[iter], sizeof(Elf64_Sym)); if (!(ELF64_ST_TYPE(symbol.st_info) == STT_FUNC || (ELF64_ST_TYPE(symbol.st_info) == STT_NOTYPE && ELF64_ST_BIND(symbol.st_info) == STB_GLOBAL))) continue; if (symbol.st_value == 0) continue; /* Sécurité anti-débordements */ if (symbol.st_name >= *str_size) continue; /* Si le symbole possède un nom... */ if (strlen(&EXE_FORMAT(format)->content[*str_start + symbol.st_name]) > 0) { format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol)); format->symbols[format->sym_count - 1].name = &EXE_FORMAT(format)->content[*str_start + symbol.st_name]; format->symbols[format->sym_count - 1].address = symbol.st_value; } } return true; } /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * comments = liste des commentaires à insérer. [OUT] * * offsets = liste des indices des commentaires. [OUT] * * count = taille des listes construites. [OUT] * * * * Description : Récupère tous les commentaires à insérer dans le code. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void get_elf_symbol_comments(const elf_format *format, char ***comments, uint64_t **offsets, size_t *count) { size_t i; /* Boucle de parcours */ size_t len; /* Longueur d'une désignation */ if (format->sym_count > 0) { *comments = (char **)calloc(*count + format->sym_count, sizeof(char *)); *offsets = (uint64_t *)calloc(*count + format->sym_count, sizeof(uint64_t)); for (i = 0; i < format->sym_count; i++) { len = strlen(format->symbols[i].name); (*comments)[i] = (char *)calloc(len + 9, sizeof(char)); snprintf((*comments)[i], len + 9, "<%s>", format->symbols[i].name); (*offsets)[i] = format->symbols[i].address; } *count += format->sym_count; } }