From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-io1-xd41.google.com (mail-io1-xd41.google.com [IPv6:2607:f8b0:4864:20::d41]) by sourceware.org (Postfix) with ESMTPS id 4231A385E825 for ; Mon, 20 Apr 2020 15:34:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 4231A385E825 Received: by mail-io1-xd41.google.com with SMTP id w4so4213572ioc.6 for ; Mon, 20 Apr 2020 08:34:37 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=I/ha+prBqXA/zfB8lUcc7Q3WWkBE0JQ6Dx4M1PEeLm8=; b=NYZKcwaylK37OPDAG9y43Cu1mi20M18eqEN50wGpRl6EX7PEJzkur2tLh7tq43woEE JvDd9D8SL81qZJ1yc4DbB6QtZKXbiH872HTt5HS/eVTathGGFKRrtJyiXd2+BDvE74zz 34GC0pDpZ4l5g/7RsychDyaKyg0yWa+5qdkIfWLGKpP9w9PUJ9zQj3AlOEja8md6ZPNb 07ftPe9npHMTL993JzDSrMD2O0ip2gma9YJ/Tp8psLxZMNMGdPiHC+D8SnLP3mNyixcx YQbgpA/iBQ/WNMpU5rH34hIuHyBtqBSmG/ngL4cnTC7mQJvutew6NsI/YC7J3UVwXx5X SkaA== X-Gm-Message-State: AGi0PuYpNc4D1tpF/NJ5Nuo8qKM7OKmCSj55kk4X7lDtRdyUoPyBTy+u jXUF0AQ6ay3zzZWIaiIJq4VA9hBshXbkNsmvy5cFFw== X-Google-Smtp-Source: APiQypJaah8vLcPWd7UURvL+DACN/kDM+GTQ3d7CKxbsHGY7Deim7MlT6iTehWT2lD6WzXsNZggQo+Q4sQZxtdY4PQQ= X-Received: by 2002:a6b:3883:: with SMTP id f125mr15156466ioa.92.1587396875839; Mon, 20 Apr 2020 08:34:35 -0700 (PDT) MIME-Version: 1.0 References: <20200420110846.218792-1-maennich@google.com> <20200420110846.218792-3-maennich@google.com> In-Reply-To: <20200420110846.218792-3-maennich@google.com> From: Giuliano Procida Date: Mon, 20 Apr 2020 16:34:19 +0100 Message-ID: Subject: Re: [PATCH 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader To: Matthias Maennich Cc: libabigail@sourceware.org, Dodji Seketeli , kernel-team@android.com Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-35.9 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, ENV_AND_HDR_SPF_MATCH, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPAM_BODY, SPF_HELO_NONE, SPF_PASS, TXREP, USER_IN_DEF_DKIM_WL, USER_IN_DEF_SPF_WL autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libabigail@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libabigail mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 20 Apr 2020 15:34:40 -0000 Looks good. On Mon, 20 Apr 2020 at 12:09, Matthias Maennich wrote: > > Move some definitions from abg-dwarf-reader to abg-elf-helpers that are > strictly only related to ELF. > > * abg-dwarf-reader.cc(stt_to_elf_symbol_type): Move function out. > (stb_to_elf_symbol_binding): Likewise. > (stv_to_elf_symbol_visibility): Likewise. > (e_machine_to_string): Likewise. > (find_section): Likewise. > (find_symbol_table_section): Likewise. > (find_symbol_table_section_index): Likewise. > (enum hash_table_kind): Likewise. > (find_hash_table_section_index): Likewise. > (get_symbol_versionning_sections): Likewise. > (find_text_section): Likewise. > (find_bss_section): Likewise. > (find_rodata_section): Likewise. > (find_data_section): Likewise. > (find_data1_section): Likewise. > * abg-elf-helpers.cc(stt_to_elf_symbol_type): Move function in. > (stb_to_elf_symbol_binding): Likewise. > (stv_to_elf_symbol_visibility): Likewise. > (e_machine_to_string): Likewise. > (find_section): Likewise. > (find_symbol_table_section): Likewise. > (find_symbol_table_section_index): Likewise. > (enum hash_table_kind): Likewise. > (find_hash_table_section_index): Likewise. > (get_symbol_versionning_sections): Likewise. > (find_text_section): Likewise. > (find_bss_section): Likewise. > (find_rodata_section): Likewise. > (find_data_section): Likewise. > (find_data1_section): Likewise. Wrong file name. > * abg-elf-helpers.cc(stt_to_elf_symbol_type): Add declaration. > (stb_to_elf_symbol_binding): Likewise. > (stv_to_elf_symbol_visibility): Likewise. > (e_machine_to_string): Likewise. > (find_section): Likewise. > (find_symbol_table_section): Likewise. > (find_symbol_table_section_index): Likewise. > (enum hash_table_kind): Likewise. > (find_hash_table_section_index): Likewise. > (get_symbol_versionning_sections): Likewise. > (find_text_section): Likewise. > (find_bss_section): Likewise. > (find_rodata_section): Likewise. > (find_data_section): Likewise. > (find_data1_section): Likewise. Reviewed-by: Giuliano Procida > Signed-off-by: Matthias Maennich > --- > src/abg-dwarf-reader.cc | 594 +--------------------------------------- > src/abg-elf-helpers.cc | 471 +++++++++++++++++++++++++++++++ > src/abg-elf-helpers.h | 65 +++++ > 3 files changed, 540 insertions(+), 590 deletions(-) > > diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc > index 1c0d6ea0353f..6ec7e4b6e968 100644 > --- a/src/abg-dwarf-reader.cc > +++ b/src/abg-dwarf-reader.cc > @@ -50,6 +50,8 @@ > #include "abg-suppression-priv.h" > #include "abg-corpus-priv.h" > > +#include "abg-elf-helpers.h" > + > #include "abg-internal.h" > // > ABG_BEGIN_EXPORT_DECLARATIONS > @@ -84,6 +86,8 @@ using std::stack; > using std::deque; > using std::list; > > +using namespace elf_helpers; // TODO: avoid using namespace > + > /// Where a DIE comes from. For instance, a DIE can come from the main > /// debug info section, the alternate debug info section or from the > /// type unit section. > @@ -290,9 +294,6 @@ static void > add_symbol_to_map(const elf_symbol_sptr& sym, > string_elf_symbols_map_type& map); > > -static bool > -find_symbol_table_section(Elf* elf_handle, Elf_Scn*& section); > - > static bool > get_symbol_versionning_sections(Elf* elf_handle, > Elf_Scn*& versym_section, > @@ -546,548 +547,6 @@ compare_dies(const read_context& ctxt, > const Dwarf_Die *l, const Dwarf_Die *r, > bool update_canonical_dies_on_the_fly); > > -/// Convert an elf symbol type (given by the ELF{32,64}_ST_TYPE > -/// macros) into an elf_symbol::type value. > -/// > -/// Note that this function aborts when given an unexpected value. > -/// > -/// @param the symbol type value to convert. > -/// > -/// @return the converted value. > -static elf_symbol::type > -stt_to_elf_symbol_type(unsigned char stt) > -{ > - elf_symbol::type t = elf_symbol::NOTYPE_TYPE; > - > - switch (stt) > - { > - case STT_NOTYPE: > - t = elf_symbol::NOTYPE_TYPE; > - break; > - case STT_OBJECT: > - t = elf_symbol::OBJECT_TYPE; > - break; > - case STT_FUNC: > - t = elf_symbol::FUNC_TYPE; > - break; > - case STT_SECTION: > - t = elf_symbol::SECTION_TYPE; > - break; > - case STT_FILE: > - t = elf_symbol::FILE_TYPE; > - break; > - case STT_COMMON: > - t = elf_symbol::COMMON_TYPE; > - break; > - case STT_TLS: > - t = elf_symbol::TLS_TYPE; > - break; > - case STT_GNU_IFUNC: > - t = elf_symbol::GNU_IFUNC_TYPE; > - break; > - default: > - // An unknown value that probably ought to be supported? Let's > - // abort right here rather than yielding garbage. > - ABG_ASSERT_NOT_REACHED; > - } > - > - return t; > -} > - > -/// Convert an elf symbol binding (given by the ELF{32,64}_ST_BIND > -/// macros) into an elf_symbol::binding value. > -/// > -/// Note that this function aborts when given an unexpected value. > -/// > -/// @param the symbol binding value to convert. > -/// > -/// @return the converted value. > -static elf_symbol::binding > -stb_to_elf_symbol_binding(unsigned char stb) > -{ > - elf_symbol::binding b = elf_symbol::GLOBAL_BINDING; > - > - switch (stb) > - { > - case STB_LOCAL: > - b = elf_symbol::LOCAL_BINDING; > - break; > - case STB_GLOBAL: > - b = elf_symbol::GLOBAL_BINDING; > - break; > - case STB_WEAK: > - b = elf_symbol::WEAK_BINDING; > - break; > - case STB_GNU_UNIQUE: > - b = elf_symbol::GNU_UNIQUE_BINDING; > - break; > - default: > - ABG_ASSERT_NOT_REACHED; > - } > - > - return b; > - > -} > - > -/// Convert an ELF symbol visiblity given by the symbols ->st_other > -/// data member as returned by the GELF_ST_VISIBILITY macro into a > -/// elf_symbol::visiblity value. > -/// > -/// @param stv the value of the ->st_other data member of the ELF > -/// symbol. > -/// > -/// @return the converted elf_symbol::visiblity value. > -static elf_symbol::visibility > -stv_to_elf_symbol_visibility(unsigned char stv) > -{ > - > - elf_symbol::visibility v = elf_symbol::DEFAULT_VISIBILITY; > - > - switch (stv) > - { > - case STV_DEFAULT: > - v = elf_symbol::DEFAULT_VISIBILITY; > - break; > - case STV_INTERNAL: > - v = elf_symbol::INTERNAL_VISIBILITY; > - break; > - case STV_HIDDEN: > - v = elf_symbol::HIDDEN_VISIBILITY; > - break; > - case STV_PROTECTED: > - v = elf_symbol::PROTECTED_VISIBILITY; > - break; > - default: > - ABG_ASSERT_NOT_REACHED; > - } > - > - return v; > -} > - > -/// Convert the value of the e_machine field of GElf_Ehdr into a > -/// string. This is to get a string representing the architecture of > -/// the elf file at hand. > -/// > -/// @param e_machine the value of GElf_Ehdr::e_machine. > -/// > -/// @return the string representation of GElf_Ehdr::e_machine. > -static string > -e_machine_to_string(GElf_Half e_machine) > -{ > - string result; > - switch (e_machine) > - { > - case EM_NONE: > - result = "elf-no-arch"; > - break; > - case EM_M32: > - result = "elf-att-we-32100"; > - break; > - case EM_SPARC: > - result = "elf-sun-sparc"; > - break; > - case EM_386: > - result = "elf-intel-80386"; > - break; > - case EM_68K: > - result = "elf-motorola-68k"; > - break; > - case EM_88K: > - result = "elf-motorola-88k"; > - break; > - case EM_860: > - result = "elf-intel-80860"; > - break; > - case EM_MIPS: > - result = "elf-mips-r3000-be"; > - break; > - case EM_S370: > - result = "elf-ibm-s370"; > - break; > - case EM_MIPS_RS3_LE: > - result = "elf-mips-r3000-le"; > - break; > - case EM_PARISC: > - result = "elf-hp-parisc"; > - break; > - case EM_VPP500: > - result = "elf-fujitsu-vpp500"; > - break; > - case EM_SPARC32PLUS: > - result = "elf-sun-sparc-v8plus"; > - break; > - case EM_960: > - result = "elf-intel-80960"; > - break; > - case EM_PPC: > - result = "elf-powerpc"; > - break; > - case EM_PPC64: > - result = "elf-powerpc-64"; > - break; > - case EM_S390: > - result = "elf-ibm-s390"; > - break; > - case EM_V800: > - result = "elf-nec-v800"; > - break; > - case EM_FR20: > - result = "elf-fujitsu-fr20"; > - break; > - case EM_RH32: > - result = "elf-trw-rh32"; > - break; > - case EM_RCE: > - result = "elf-motorola-rce"; > - break; > - case EM_ARM: > - result = "elf-arm"; > - break; > - case EM_FAKE_ALPHA: > - result = "elf-digital-alpha"; > - break; > - case EM_SH: > - result = "elf-hitachi-sh"; > - break; > - case EM_SPARCV9: > - result = "elf-sun-sparc-v9-64"; > - break; > - case EM_TRICORE: > - result = "elf-siemens-tricore"; > - break; > - case EM_ARC: > - result = "elf-argonaut-risc-core"; > - break; > - case EM_H8_300: > - result = "elf-hitachi-h8-300"; > - break; > - case EM_H8_300H: > - result = "elf-hitachi-h8-300h"; > - break; > - case EM_H8S: > - result = "elf-hitachi-h8s"; > - break; > - case EM_H8_500: > - result = "elf-hitachi-h8-500"; > - break; > - case EM_IA_64: > - result = "elf-intel-ia-64"; > - break; > - case EM_MIPS_X: > - result = "elf-stanford-mips-x"; > - break; > - case EM_COLDFIRE: > - result = "elf-motorola-coldfire"; > - break; > - case EM_68HC12: > - result = "elf-motorola-68hc12"; > - break; > - case EM_MMA: > - result = "elf-fujitsu-mma"; > - break; > - case EM_PCP: > - result = "elf-siemens-pcp"; > - break; > - case EM_NCPU: > - result = "elf-sony-ncpu"; > - break; > - case EM_NDR1: > - result = "elf-denso-ndr1"; > - break; > - case EM_STARCORE: > - result = "elf-motorola-starcore"; > - break; > - case EM_ME16: > - result = "elf-toyota-me16"; > - break; > - case EM_ST100: > - result = "elf-stm-st100"; > - break; > - case EM_TINYJ: > - result = "elf-alc-tinyj"; > - break; > - case EM_X86_64: > - result = "elf-amd-x86_64"; > - break; > - case EM_PDSP: > - result = "elf-sony-pdsp"; > - break; > - case EM_FX66: > - result = "elf-siemens-fx66"; > - break; > - case EM_ST9PLUS: > - result = "elf-stm-st9+"; > - break; > - case EM_ST7: > - result = "elf-stm-st7"; > - break; > - case EM_68HC16: > - result = "elf-motorola-68hc16"; > - break; > - case EM_68HC11: > - result = "elf-motorola-68hc11"; > - break; > - case EM_68HC08: > - result = "elf-motorola-68hc08"; > - break; > - case EM_68HC05: > - result = "elf-motorola-68hc05"; > - break; > - case EM_SVX: > - result = "elf-sg-svx"; > - break; > - case EM_ST19: > - result = "elf-stm-st19"; > - break; > - case EM_VAX: > - result = "elf-digital-vax"; > - break; > - case EM_CRIS: > - result = "elf-axis-cris"; > - break; > - case EM_JAVELIN: > - result = "elf-infineon-javelin"; > - break; > - case EM_FIREPATH: > - result = "elf-firepath"; > - break; > - case EM_ZSP: > - result = "elf-lsi-zsp"; > - break; > - case EM_MMIX: > - result = "elf-don-knuth-mmix"; > - break; > - case EM_HUANY: > - result = "elf-harvard-huany"; > - break; > - case EM_PRISM: > - result = "elf-sitera-prism"; > - break; > - case EM_AVR: > - result = "elf-atmel-avr"; > - break; > - case EM_FR30: > - result = "elf-fujistu-fr30"; > - break; > - case EM_D10V: > - result = "elf-mitsubishi-d10v"; > - break; > - case EM_D30V: > - result = "elf-mitsubishi-d30v"; > - break; > - case EM_V850: > - result = "elf-nec-v850"; > - break; > - case EM_M32R: > - result = "elf-mitsubishi-m32r"; > - break; > - case EM_MN10300: > - result = "elf-matsushita-mn10300"; > - break; > - case EM_MN10200: > - result = "elf-matsushita-mn10200"; > - break; > - case EM_PJ: > - result = "elf-picojava"; > - break; > - case EM_OPENRISC: > - result = "elf-openrisc-32"; > - break; > - case EM_ARC_A5: > - result = "elf-arc-a5"; > - break; > - case EM_XTENSA: > - result = "elf-tensilica-xtensa"; > - break; > - > -#ifdef HAVE_EM_AARCH64_MACRO > - case EM_AARCH64: > - result = "elf-arm-aarch64"; > - break; > -#endif > - > -#ifdef HAVE_EM_TILEPRO_MACRO > - case EM_TILEPRO: > - result = "elf-tilera-tilepro"; > - break; > -#endif > - > -#ifdef HAVE_EM_TILEGX_MACRO > - case EM_TILEGX: > - result = "elf-tilera-tilegx"; > - break; > -#endif > - > - case EM_NUM: > - result = "elf-last-arch-number"; > - break; > - case EM_ALPHA: > - result = "elf-non-official-alpha"; > - break; > - default: > - { > - std::ostringstream o; > - o << "elf-unknown-arch-value-" << e_machine; > - result = o.str(); > - } > - break; > - } > - return result; > -} > - > -/// The kind of ELF hash table found by the function > -/// find_hash_table_section_index. > -enum hash_table_kind > -{ > - NO_HASH_TABLE_KIND = 0, > - SYSV_HASH_TABLE_KIND, > - GNU_HASH_TABLE_KIND > -}; > - > -/// Get the offset offset of the hash table section. > -/// > -/// @param elf_handle the elf handle to use. > -/// > -/// @param ht_section_offset this is set to the resulting offset > -/// of the hash table section. This is set iff the function returns true. > -/// > -/// @param symtab_section_offset the offset of the section of the > -/// symbol table the hash table refers to. > -static hash_table_kind > -find_hash_table_section_index(Elf* elf_handle, > - size_t& ht_section_index, > - size_t& symtab_section_index) > -{ > - if (!elf_handle) > - return NO_HASH_TABLE_KIND; > - > - GElf_Shdr header_mem, *section_header; > - bool found_sysv_ht = false, found_gnu_ht = false; > - for (Elf_Scn* section = elf_nextscn(elf_handle, 0); > - section != 0; > - section = elf_nextscn(elf_handle, section)) > - { > - section_header= gelf_getshdr(section, &header_mem); > - if (section_header->sh_type != SHT_HASH > - && section_header->sh_type != SHT_GNU_HASH) > - continue; > - > - ht_section_index = elf_ndxscn(section); > - symtab_section_index = section_header->sh_link; > - > - if (section_header->sh_type == SHT_HASH) > - found_sysv_ht = true; > - else if (section_header->sh_type == SHT_GNU_HASH) > - found_gnu_ht = true; > - } > - > - if (found_gnu_ht) > - return GNU_HASH_TABLE_KIND; > - else if (found_sysv_ht) > - return SYSV_HASH_TABLE_KIND; > - else > - return NO_HASH_TABLE_KIND; > -} > - > -/// Find the symbol table. > -/// > -/// If we are looking at a relocatable or executable file, this > -/// function will return the .symtab symbol table (of type > -/// SHT_SYMTAB). But if we are looking at a DSO it returns the > -/// .dynsym symbol table (of type SHT_DYNSYM). > -/// > -/// @param elf_handle the elf handle to consider. > -/// > -/// @param symtab the symbol table found. > -/// > -/// @return true iff the symbol table is found. > -static bool > -find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab) > -{ > - Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0; > - while ((section = elf_nextscn(elf_handle, section)) != 0) > - { > - GElf_Shdr header_mem, *header; > - header = gelf_getshdr(section, &header_mem); > - if (header->sh_type == SHT_DYNSYM) > - dynsym = section; > - else if (header->sh_type == SHT_SYMTAB) > - sym_tab = section; > - } > - > - if (dynsym || sym_tab) > - { > - GElf_Ehdr eh_mem; > - GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem); > - if (elf_header->e_type == ET_REL > - || elf_header->e_type == ET_EXEC) > - symtab = sym_tab ? sym_tab : dynsym; > - else > - symtab = dynsym ? dynsym : sym_tab; > - return true; > - } > - return false; > -} > - > -/// Find the index (in the section headers table) of the symbol table > -/// section. > -/// > -/// If we are looking at a relocatable or executable file, this > -/// function will return the index for the .symtab symbol table (of > -/// type SHT_SYMTAB). But if we are looking at a DSO it returns the > -/// index for the .dynsym symbol table (of type SHT_DYNSYM). > -/// > -/// @param elf_handle the elf handle to use. > -/// > -/// @param symtab_index the index of the symbol_table, that was found. > -/// > -/// @return true iff the symbol table section index was found. > -static bool > -find_symbol_table_section_index(Elf* elf_handle, > - size_t& symtab_index) > -{ > - Elf_Scn* section = 0; > - if (!find_symbol_table_section(elf_handle, section)) > - return false; > - > - symtab_index = elf_ndxscn(section); > - return true; > -} > - > -/// Find and return a section by its name and its type. > -/// > -/// @param elf_handle the elf handle to use. > -/// > -/// @param name the name of the section. > -/// > -/// @param section_type the type of the section. This is the > -/// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member. > -/// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS. > -/// > -/// @return the section found, nor nil if none was found. > -static Elf_Scn* > -find_section(Elf* elf_handle, const string& name, Elf64_Word section_type) > -{ > - size_t section_header_string_index = 0; > - if (elf_getshdrstrndx (elf_handle, §ion_header_string_index) < 0) > - return 0; > - > - Elf_Scn* section = 0; > - GElf_Shdr header_mem, *header; > - while ((section = elf_nextscn(elf_handle, section)) != 0) > - { > - header = gelf_getshdr(section, &header_mem); > - if (header == NULL || header->sh_type != section_type) > - continue; > - > - const char* section_name = > - elf_strptr(elf_handle, section_header_string_index, header->sh_name); > - if (section_name && name == section_name) > - return section; > - } > - > - return 0; > -} > > /// Test if the ELF binary denoted by a given ELF handle is a Linux > /// Kernel Module. > @@ -1121,51 +580,6 @@ binary_is_linux_kernel(Elf *elf_handle) > || binary_is_linux_kernel_module(elf_handle)); > } > > -/// Find and return the .text section. > -/// > -/// @param elf_handle the elf handle to use. > -/// > -/// @return the .text section found. > -static Elf_Scn* > -find_text_section(Elf* elf_handle) > -{return find_section(elf_handle, ".text", SHT_PROGBITS);} > - > -/// Find and return the .bss section. > -/// > -/// @param elf_handle. > -/// > -/// @return the .bss section found. > -static Elf_Scn* > -find_bss_section(Elf* elf_handle) > -{return find_section(elf_handle, ".bss", SHT_NOBITS);} > - > -/// Find and return the .rodata section. > -/// > -/// @param elf_handle. > -/// > -/// @return the .rodata section found. > -static Elf_Scn* > -find_rodata_section(Elf* elf_handle) > -{return find_section(elf_handle, ".rodata", SHT_PROGBITS);} > - > -/// Find and return the .data section. > -/// > -/// @param elf_handle the elf handle to use. > -/// > -/// @return the .data section found. > -static Elf_Scn* > -find_data_section(Elf* elf_handle) > -{return find_section(elf_handle, ".data", SHT_PROGBITS);} > - > -/// Find and return the .data1 section. > -/// > -/// @param elf_handle the elf handle to use. > -/// > -/// @return the .data1 section found. > -static Elf_Scn* > -find_data1_section(Elf* elf_handle) > -{return find_section(elf_handle, ".data1", SHT_PROGBITS);} > - > /// Find the __ksymtab_strings section of a Linux kernel binary. > /// > /// > diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc > index e99fe4a5c306..b0113a4efd2c 100644 > --- a/src/abg-elf-helpers.cc > +++ b/src/abg-elf-helpers.cc > @@ -24,11 +24,482 @@ > > #include "abg-elf-helpers.h" > > +#include > + > +#include "abg-tools-utils.h" > + > namespace abigail > { > > namespace elf_helpers > { > > +/// Convert an elf symbol type (given by the ELF{32,64}_ST_TYPE > +/// macros) into an elf_symbol::type value. > +/// > +/// Note that this function aborts when given an unexpected value. > +/// > +/// @param the symbol type value to convert. > +/// > +/// @return the converted value. > +elf_symbol::type > +stt_to_elf_symbol_type(unsigned char stt) > +{ > + switch (stt) > + { > + case STT_NOTYPE: > + return elf_symbol::NOTYPE_TYPE; > + case STT_OBJECT: > + return elf_symbol::OBJECT_TYPE; > + case STT_FUNC: > + return elf_symbol::FUNC_TYPE; > + case STT_SECTION: > + return elf_symbol::SECTION_TYPE; > + case STT_FILE: > + return elf_symbol::FILE_TYPE; > + case STT_COMMON: > + return elf_symbol::COMMON_TYPE; > + case STT_TLS: > + return elf_symbol::TLS_TYPE; > + case STT_GNU_IFUNC: > + return elf_symbol::GNU_IFUNC_TYPE; > + default: > + // An unknown value that probably ought to be supported? Let's > + // abort right here rather than yielding garbage. > + ABG_ASSERT_NOT_REACHED; > + } > +} > + > +/// Convert an elf symbol binding (given by the ELF{32,64}_ST_BIND > +/// macros) into an elf_symbol::binding value. > +/// > +/// Note that this function aborts when given an unexpected value. > +/// > +/// @param the symbol binding value to convert. > +/// > +/// @return the converted value. > +elf_symbol::binding > +stb_to_elf_symbol_binding(unsigned char stb) > +{ > + switch (stb) > + { > + case STB_LOCAL: > + return elf_symbol::LOCAL_BINDING; > + case STB_GLOBAL: > + return elf_symbol::GLOBAL_BINDING; > + case STB_WEAK: > + return elf_symbol::WEAK_BINDING; > + case STB_GNU_UNIQUE: > + return elf_symbol::GNU_UNIQUE_BINDING; > + default: > + ABG_ASSERT_NOT_REACHED; > + } > +} > + > +/// Convert an ELF symbol visiblity given by the symbols ->st_other > +/// data member as returned by the GELF_ST_VISIBILITY macro into a > +/// elf_symbol::visiblity value. > +/// > +/// @param stv the value of the ->st_other data member of the ELF > +/// symbol. > +/// > +/// @return the converted elf_symbol::visiblity value. > +elf_symbol::visibility > +stv_to_elf_symbol_visibility(unsigned char stv) > +{ > + switch (stv) > + { > + case STV_DEFAULT: > + return elf_symbol::DEFAULT_VISIBILITY; > + case STV_INTERNAL: > + return elf_symbol::INTERNAL_VISIBILITY; > + case STV_HIDDEN: > + return elf_symbol::HIDDEN_VISIBILITY; > + case STV_PROTECTED: > + return elf_symbol::PROTECTED_VISIBILITY; > + default: > + ABG_ASSERT_NOT_REACHED; > + } > +} > + > +/// Convert the value of the e_machine field of GElf_Ehdr into a > +/// string. This is to get a string representing the architecture of > +/// the elf file at hand. > +/// > +/// @param e_machine the value of GElf_Ehdr::e_machine. > +/// > +/// @return the string representation of GElf_Ehdr::e_machine. > +std::string > +e_machine_to_string(GElf_Half e_machine) > +{ > + switch (e_machine) > + { > + case EM_NONE: > + return "elf-no-arch"; > + case EM_M32: > + return "elf-att-we-32100"; > + case EM_SPARC: > + return "elf-sun-sparc"; > + case EM_386: > + return "elf-intel-80386"; > + case EM_68K: > + return "elf-motorola-68k"; > + case EM_88K: > + return "elf-motorola-88k"; > + case EM_860: > + return "elf-intel-80860"; > + case EM_MIPS: > + return "elf-mips-r3000-be"; > + case EM_S370: > + return "elf-ibm-s370"; > + case EM_MIPS_RS3_LE: > + return "elf-mips-r3000-le"; > + case EM_PARISC: > + return "elf-hp-parisc"; > + case EM_VPP500: > + return "elf-fujitsu-vpp500"; > + case EM_SPARC32PLUS: > + return "elf-sun-sparc-v8plus"; > + case EM_960: > + return "elf-intel-80960"; > + case EM_PPC: > + return "elf-powerpc"; > + case EM_PPC64: > + return "elf-powerpc-64"; > + case EM_S390: > + return "elf-ibm-s390"; > + case EM_V800: > + return "elf-nec-v800"; > + case EM_FR20: > + return "elf-fujitsu-fr20"; > + case EM_RH32: > + return "elf-trw-rh32"; > + case EM_RCE: > + return "elf-motorola-rce"; > + case EM_ARM: > + return "elf-arm"; > + case EM_FAKE_ALPHA: > + return "elf-digital-alpha"; > + case EM_SH: > + return "elf-hitachi-sh"; > + case EM_SPARCV9: > + return "elf-sun-sparc-v9-64"; > + case EM_TRICORE: > + return "elf-siemens-tricore"; > + case EM_ARC: > + return "elf-argonaut-risc-core"; > + case EM_H8_300: > + return "elf-hitachi-h8-300"; > + case EM_H8_300H: > + return "elf-hitachi-h8-300h"; > + case EM_H8S: > + return "elf-hitachi-h8s"; > + case EM_H8_500: > + return "elf-hitachi-h8-500"; > + case EM_IA_64: > + return "elf-intel-ia-64"; > + case EM_MIPS_X: > + return "elf-stanford-mips-x"; > + case EM_COLDFIRE: > + return "elf-motorola-coldfire"; > + case EM_68HC12: > + return "elf-motorola-68hc12"; > + case EM_MMA: > + return "elf-fujitsu-mma"; > + case EM_PCP: > + return "elf-siemens-pcp"; > + case EM_NCPU: > + return "elf-sony-ncpu"; > + case EM_NDR1: > + return "elf-denso-ndr1"; > + case EM_STARCORE: > + return "elf-motorola-starcore"; > + case EM_ME16: > + return "elf-toyota-me16"; > + case EM_ST100: > + return "elf-stm-st100"; > + case EM_TINYJ: > + return "elf-alc-tinyj"; > + case EM_X86_64: > + return "elf-amd-x86_64"; > + case EM_PDSP: > + return "elf-sony-pdsp"; > + case EM_FX66: > + return "elf-siemens-fx66"; > + case EM_ST9PLUS: > + return "elf-stm-st9+"; > + case EM_ST7: > + return "elf-stm-st7"; > + case EM_68HC16: > + return "elf-motorola-68hc16"; > + case EM_68HC11: > + return "elf-motorola-68hc11"; > + case EM_68HC08: > + return "elf-motorola-68hc08"; > + case EM_68HC05: > + return "elf-motorola-68hc05"; > + case EM_SVX: > + return "elf-sg-svx"; > + case EM_ST19: > + return "elf-stm-st19"; > + case EM_VAX: > + return "elf-digital-vax"; > + case EM_CRIS: > + return "elf-axis-cris"; > + case EM_JAVELIN: > + return "elf-infineon-javelin"; > + case EM_FIREPATH: > + return "elf-firepath"; > + case EM_ZSP: > + return "elf-lsi-zsp"; > + case EM_MMIX: > + return "elf-don-knuth-mmix"; > + case EM_HUANY: > + return "elf-harvard-huany"; > + case EM_PRISM: > + return "elf-sitera-prism"; > + case EM_AVR: > + return "elf-atmel-avr"; > + case EM_FR30: > + return "elf-fujistu-fr30"; > + case EM_D10V: > + return "elf-mitsubishi-d10v"; > + case EM_D30V: > + return "elf-mitsubishi-d30v"; > + case EM_V850: > + return "elf-nec-v850"; > + case EM_M32R: > + return "elf-mitsubishi-m32r"; > + case EM_MN10300: > + return "elf-matsushita-mn10300"; > + case EM_MN10200: > + return "elf-matsushita-mn10200"; > + case EM_PJ: > + return "elf-picojava"; > + case EM_OPENRISC: > + return "elf-openrisc-32"; > + case EM_ARC_A5: > + return "elf-arc-a5"; > + case EM_XTENSA: > + return "elf-tensilica-xtensa"; > + > +#ifdef HAVE_EM_AARCH64_MACRO > + case EM_AARCH64: > + return "elf-arm-aarch64"; > +#endif > + > +#ifdef HAVE_EM_TILEPRO_MACRO > + case EM_TILEPRO: > + return "elf-tilera-tilepro"; > +#endif > + > +#ifdef HAVE_EM_TILEGX_MACRO > + case EM_TILEGX: > + return "elf-tilera-tilegx"; > +#endif > + > + case EM_NUM: > + return "elf-last-arch-number"; > + case EM_ALPHA: > + return "elf-non-official-alpha"; > + default: > + { > + std::ostringstream o; > + o << "elf-unknown-arch-value-" << e_machine; > + return o.str(); > + } > + } > +} > + > +/// Find and return a section by its name and its type. > +/// > +/// @param elf_handle the elf handle to use. > +/// > +/// @param name the name of the section. > +/// > +/// @param section_type the type of the section. This is the > +/// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member. > +/// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS. > +/// > +/// @return the section found, nor nil if none was found. > +Elf_Scn* > +find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type) > +{ > + size_t section_header_string_index = 0; > + if (elf_getshdrstrndx (elf_handle, §ion_header_string_index) < 0) > + return 0; > + > + Elf_Scn* section = 0; > + GElf_Shdr header_mem, *header; > + while ((section = elf_nextscn(elf_handle, section)) != 0) > + { > + header = gelf_getshdr(section, &header_mem); > + if (header == NULL || header->sh_type != section_type) > + continue; > + > + const char* section_name = > + elf_strptr(elf_handle, section_header_string_index, header->sh_name); > + if (section_name && name == section_name) > + return section; > + } > + > + return 0; > +} > + > +/// Find the symbol table. > +/// > +/// If we are looking at a relocatable or executable file, this > +/// function will return the .symtab symbol table (of type > +/// SHT_SYMTAB). But if we are looking at a DSO it returns the > +/// .dynsym symbol table (of type SHT_DYNSYM). > +/// > +/// @param elf_handle the elf handle to consider. > +/// > +/// @param symtab the symbol table found. > +/// > +/// @return true iff the symbol table is found. > +bool > +find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab) > +{ > + Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0; > + while ((section = elf_nextscn(elf_handle, section)) != 0) > + { > + GElf_Shdr header_mem, *header; > + header = gelf_getshdr(section, &header_mem); > + if (header->sh_type == SHT_DYNSYM) > + dynsym = section; > + else if (header->sh_type == SHT_SYMTAB) > + sym_tab = section; > + } > + > + if (dynsym || sym_tab) > + { > + GElf_Ehdr eh_mem; > + GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem); > + if (elf_header->e_type == ET_REL > + || elf_header->e_type == ET_EXEC) > + symtab = sym_tab ? sym_tab : dynsym; > + else > + symtab = dynsym ? dynsym : sym_tab; > + return true; > + } > + return false; > +} > + > +/// Find the index (in the section headers table) of the symbol table > +/// section. > +/// > +/// If we are looking at a relocatable or executable file, this > +/// function will return the index for the .symtab symbol table (of > +/// type SHT_SYMTAB). But if we are looking at a DSO it returns the > +/// index for the .dynsym symbol table (of type SHT_DYNSYM). > +/// > +/// @param elf_handle the elf handle to use. > +/// > +/// @param symtab_index the index of the symbol_table, that was found. > +/// > +/// @return true iff the symbol table section index was found. > +bool > +find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index) > +{ > + Elf_Scn* section = 0; > + if (!find_symbol_table_section(elf_handle, section)) > + return false; > + > + symtab_index = elf_ndxscn(section); > + return true; > +} > + > +/// Get the offset offset of the hash table section. > +/// > +/// @param elf_handle the elf handle to use. > +/// > +/// @param ht_section_offset this is set to the resulting offset > +/// of the hash table section. This is set iff the function returns true. > +/// > +/// @param symtab_section_offset the offset of the section of the > +/// symbol table the hash table refers to. > +hash_table_kind > +find_hash_table_section_index(Elf* elf_handle, > + size_t& ht_section_index, > + size_t& symtab_section_index) > +{ > + if (!elf_handle) > + return NO_HASH_TABLE_KIND; > + > + GElf_Shdr header_mem, *section_header; > + bool found_sysv_ht = false, found_gnu_ht = false; > + for (Elf_Scn* section = elf_nextscn(elf_handle, 0); > + section != 0; > + section = elf_nextscn(elf_handle, section)) > + { > + section_header= gelf_getshdr(section, &header_mem); > + if (section_header->sh_type != SHT_HASH > + && section_header->sh_type != SHT_GNU_HASH) > + continue; > + > + ht_section_index = elf_ndxscn(section); > + symtab_section_index = section_header->sh_link; > + > + if (section_header->sh_type == SHT_HASH) > + found_sysv_ht = true; > + else if (section_header->sh_type == SHT_GNU_HASH) > + found_gnu_ht = true; > + } > + > + if (found_gnu_ht) > + return GNU_HASH_TABLE_KIND; > + else if (found_sysv_ht) > + return SYSV_HASH_TABLE_KIND; > + else > + return NO_HASH_TABLE_KIND; > +} > + > +/// Find and return the .text section. > +/// > +/// @param elf_handle the elf handle to use. > +/// > +/// @return the .text section found. > +Elf_Scn* > +find_text_section(Elf* elf_handle) > +{return find_section(elf_handle, ".text", SHT_PROGBITS);} > + > +/// Find and return the .bss section. > +/// > +/// @param elf_handle. > +/// > +/// @return the .bss section found. > +Elf_Scn* > +find_bss_section(Elf* elf_handle) > +{return find_section(elf_handle, ".bss", SHT_NOBITS);} > + > +/// Find and return the .rodata section. > +/// > +/// @param elf_handle. > +/// > +/// @return the .rodata section found. > +Elf_Scn* > +find_rodata_section(Elf* elf_handle) > +{return find_section(elf_handle, ".rodata", SHT_PROGBITS);} > + > +/// Find and return the .data section. > +/// > +/// @param elf_handle the elf handle to use. > +/// > +/// @return the .data section found. > +Elf_Scn* > +find_data_section(Elf* elf_handle) > +{return find_section(elf_handle, ".data", SHT_PROGBITS);} > + > +/// Find and return the .data1 section. > +/// > +/// @param elf_handle the elf handle to use. > +/// > +/// @return the .data1 section found. > +Elf_Scn* > +find_data1_section(Elf* elf_handle) > +{return find_section(elf_handle, ".data1", SHT_PROGBITS);} > + > + > } // end namespace elf_helpers > } // end namespace abigail > diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h > index bffa46cc3c2d..58720da0fa9e 100644 > --- a/src/abg-elf-helpers.h > +++ b/src/abg-elf-helpers.h > @@ -25,12 +25,77 @@ > #ifndef __ABG_ELF_HELPERS_H__ > #define __ABG_ELF_HELPERS_H__ > > +#include "config.h" > + > +#include > +#include > + > +#include "abg-ir.h" > + > namespace abigail > { > > namespace elf_helpers > { > > +// > +// ELF Value Converters > +// > + > +elf_symbol::type > +stt_to_elf_symbol_type(unsigned char stt); > + > +elf_symbol::binding > +stb_to_elf_symbol_binding(unsigned char stb); > + > +elf_symbol::visibility > +stv_to_elf_symbol_visibility(unsigned char stv); > + > +std::string > +e_machine_to_string(GElf_Half e_machine); > + > +// > +// ELF section helpers > +// > + > +Elf_Scn* > +find_section(Elf* elf_handle, > + const std::string& name, > + Elf64_Word section_type); > + > +bool > +find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab); > + > +bool > +find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index); > + > +enum hash_table_kind > +{ > + NO_HASH_TABLE_KIND = 0, > + SYSV_HASH_TABLE_KIND, > + GNU_HASH_TABLE_KIND > +}; > + > +hash_table_kind > +find_hash_table_section_index(Elf* elf_handle, > + size_t& ht_section_index, > + size_t& symtab_section_index); > + > +Elf_Scn* > +find_text_section(Elf* elf_handle); > + > +Elf_Scn* > +find_bss_section(Elf* elf_handle); > + > +Elf_Scn* > +find_rodata_section(Elf* elf_handle); > + > +Elf_Scn* > +find_data_section(Elf* elf_handle); > + > +Elf_Scn* > +find_data1_section(Elf* elf_handle); > + > } // end namespace elf_helpers > } // end namespace abigail > > -- > 2.26.1.301.g55bc3eb7cb9-goog >