/* Chrysalide - Outil d'analyse de fichiers binaires
* strtab.h - présentation des chaînes liées au format des binaires ELF
*
* Copyright (C) 2017-2019 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* Chrysalide 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.
*
* Chrysalide 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 Chrysalide. If not, see .
*/
#include "strtab.h"
#include
#include
#include
#include
#include
/* Affiche les chaînes présentes dans une zone de données. */
static void parse_elf_string_table(GElfFormat *, GPreloadInfo *, const GBinContent *, const mrange_t *, GtkStatusStack *);
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à compléter. *
* info = informations à constituer en avance de phase. *
* content = contenu binaire à analyser. *
* range = espace à couvrir pendant l'analyse. *
* status = barre de statut à tenir informée. *
* *
* Description : Affiche les chaînes présentes dans une zone de données. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void parse_elf_string_table(GElfFormat *format, GPreloadInfo *info, const GBinContent *content, const mrange_t *range, GtkStatusStack *status)
{
phys_t length; /* Taille de la couverture */
vmpa2t pos; /* Tête de lecture */
const bin_t *data; /* Donnés à parcourir */
bool cut; /* Séparation nette ? */
GBinFormat *base; /* Autre version du format */
phys_t i; /* Boucle de parcours */
phys_t end; /* Position de fin de chaîne */
GArchInstruction *instr; /* Instruction décodée */
bool inserted; /* Bilan d'une insertion */
const mrange_t *irange; /* Espace occupé par une chaîne*/
GBinSymbol *symbol; /* Symbole à intégrer */
length = get_mrange_length(range);
copy_vmpa(&pos, get_mrange_addr(range));
data = g_binary_content_get_raw_access(content, &pos, length);
/**
* Si la section demandée est anormalement grande (cf. exemple de la suite de
* tests "tests/format/elf/oob_section_name.asm")...
*/
if (data == NULL) return;
/* Boucle de parcours */
cut = true;
base = G_BIN_FORMAT(format);
for (i = 0; i < length; i++)
if (isprint(data[i]))
{
for (end = i + 1; end < length; end++)
if (!isprint(data[end])) break;
if (end < length && isspace(data[end]))
end++;
if (end < length && data[end] == '\0')
end++;
copy_vmpa(&pos, get_mrange_addr(range));
advance_vmpa(&pos, i);
instr = g_raw_instruction_new_array(content, MDS_8_BITS, end - i, &pos, MDS_UNDEFINED);
assert(instr != NULL);
g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true);
/**
* Comme g_preload_info_add_instruction() peut consommer l'instruction
* et qu'on réutilise cette dernière ensuite avec g_arch_instruction_get_range()...
*/
g_object_ref(G_OBJECT(instr));
inserted = g_preload_info_add_instruction(info, instr);
if (inserted)
{
irange = g_arch_instruction_get_range(instr);
symbol = g_string_symbol_new_read_only(base, irange, SET_GUESS);
g_object_ref(G_OBJECT(symbol));
g_binary_format_add_symbol(base, symbol);
/* Jointure avec la chaîne précédente ? */
if (cut)
g_string_symbol_build_label(G_STR_SYMBOL(symbol), base);
g_object_unref(G_OBJECT(symbol));
}
g_object_unref(G_OBJECT(instr));
/* Conclusion */
cut = (data[end - 1] == '\0');
i = end - 1;
}
else cut = true;
}
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à compléter. *
* info = informations à constituer en avance de phase. *
* status = barre de statut à tenir informée. *
* *
* Description : Affiche les chaînes liées aux sections ELF. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void show_elf_section_string_table(GElfFormat *format, GPreloadInfo *info, GtkStatusStack *status)
{
GBinContent *content; /* Contenu binaire à lire */
mrange_t range; /* Espace à parcourir */
bool found; /* Détection d'une section */
content = g_binary_format_get_content(G_BIN_FORMAT(format));
found = find_elf_section_range_by_name(format, ".interp", &range);
if (found)
parse_elf_string_table(format, info, content, &range, status);
found = find_elf_section_range_by_name(format, ".shstrtab", &range);
if (found)
parse_elf_string_table(format, info, content, &range, status);
found = find_elf_section_range_by_name(format, ".strtab", &range);
if (found)
parse_elf_string_table(format, info, content, &range, status);
g_object_unref(G_OBJECT(content));
}