From patchwork Wed Jan 27 12:58:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Matthias_M=C3=A4nnich?= X-Patchwork-Id: 41847 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DC6CF397303B; Wed, 27 Jan 2021 12:59:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DC6CF397303B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1611752377; bh=3UNTVFfJXRA44mQ6KDmlIB5otHyQCbI6yIrMyf/LedE=; h=Date:In-Reply-To:References:Subject:To:List-Id:List-Unsubscribe: List-Archive:List-Help:List-Subscribe:From:Reply-To:Cc:From; b=V0Rj94t6GtC8poK7YwV1RMRu0vXMtE8oT32i/F6CAYz9emYUvWrKeozzfLkUzG6/C epIelUlgs5asiIlRyGp/ojld6Zn/0f0wYpK9LZvRaPJ5r6W9Vcp+d8PF0I7he+ob7V fGy/plIJW91wvqAMKDyT+BegTmHzeoI9vvtE9/pk= X-Original-To: libabigail@sourceware.org Delivered-To: libabigail@sourceware.org Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a]) by sourceware.org (Postfix) with ESMTPS id 99323397282F for ; Wed, 27 Jan 2021 12:59:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 99323397282F Received: by mail-qk1-x74a.google.com with SMTP id 185so1379900qkl.6 for ; Wed, 27 Jan 2021 04:59:35 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=3UNTVFfJXRA44mQ6KDmlIB5otHyQCbI6yIrMyf/LedE=; b=uiABgXxlBsq9cymZQLP9ezeN0db0w6jW7jC7qya1U9vTjKwa8Lfxjzgcjxw7fVRmDv QGAHeweJOc+Vmezf3y9XzD8tDj5/KqZytRHRDJ9In8pvSmEwC+sRpnUiUTCjbKvbtG1C NGsca8uq4KaSB2GmNOwj4r+bxUW5KQsSKsPeIL6ddkwwLLEnb5trBO720SMqO5Z/rJ2F 4l8Eu1CCXP162t5wF+YRJFZ5scQEbN6kE3BLrJa/B5jBGpa2TTv5VTlrKOIGeqZGmFW2 nutRmGSYo6140p+352/EnUMFv0ztTPIxEwkwGmVb3jPZ3jvViHNrI/utAba4yclkG5Mc UudQ== X-Gm-Message-State: AOAM531ZnT0bc6rP9i3sOCl0W7TlrZmxR/iBinDCjvbkNCo8/Ti039bz p6lyz0fwPk/uiLh/3i/1uaI55sjgYaBFOK9Zgg7XngroHND5A4Iaf9fNtL9etKZ+EiFHr9k5cae WGAT/ohlF8pTb43O0i5a65q0CJwbthPtp4n0Q5Bz7r7CzuR1vFBdzjc/Ifsf0qdvGwGdjP4Y= X-Google-Smtp-Source: ABdhPJxYuxxLiAVlEtkXMdamB32SLtd4wIgLV3Bf0dEGOh84RVYixeEDlhnCbm+9CUMEUyrxIEs16v1Qwy1QrA== X-Received: from lux.lon.corp.google.com ([2a00:79e0:d:210:7220:84ff:fe09:a3aa]) (user=maennich job=sendgmr) by 2002:a0c:b409:: with SMTP id u9mr10322770qve.51.1611752375149; Wed, 27 Jan 2021 04:59:35 -0800 (PST) Date: Wed, 27 Jan 2021 12:58:46 +0000 In-Reply-To: <20210127125853.886677-1-maennich@google.com> Message-Id: <20210127125853.886677-14-maennich@google.com> Mime-Version: 1.0 References: <20200619214305.562-1-maennich@google.com> <20210127125853.886677-1-maennich@google.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog Subject: [PATCH 13/20] symtab_reader: add support for ppc64 ELFv1 binaries To: libabigail@sourceware.org X-Spam-Status: No, score=-22.8 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, USER_IN_DEF_DKIM_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: Mailing list of the Libabigail project List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-Patchwork-Original-From: Matthias Maennich via Libabigail From: =?utf-8?q?Matthias_M=C3=A4nnich?= Reply-To: Matthias Maennich Cc: maennich@google.com, kernel-team@android.com Errors-To: libabigail-bounces@sourceware.org Sender: "Libabigail" When loading the symtab from an ppc64 binary, also keep track of the function entry addresses as a key for the symbol lookup. That accommodates the differences in DWARF pointing to the function entry address while the symbol table points to the function pointer. The implementation is mostly copied and adopted from abg-dwarf-reader's read_context to add this functionality also to the new symtab reader. * src/abg-symtab-reader.cc (symtab::lookup_symbol): fall back to lookup the address in entry_addr_symbol_map_. (symtab::load): update the function entry address map for ppc64 targets. (symtab::update_function_entry_address_symbol_map): New function implementation. * src/abg-symtab-reader.h (symtab::entry_addr_symbol_map_): New data member. (symtab::update_function_entry_address_symbol_map): New function declaration. Reviewed-by: Giuliano Procida Signed-off-by: Matthias Maennich --- src/abg-symtab-reader.cc | 93 ++++++++++++++++++++++++++++++++++++++-- src/abg-symtab-reader.h | 8 ++++ 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/src/abg-symtab-reader.cc b/src/abg-symtab-reader.cc index 4576be2a0b42..7318fdfce52e 100644 --- a/src/abg-symtab-reader.cc +++ b/src/abg-symtab-reader.cc @@ -100,9 +100,15 @@ const elf_symbol_sptr& symtab::lookup_symbol(GElf_Addr symbol_addr) const { static const elf_symbol_sptr empty_result; - const auto it = addr_symbol_map_.find(symbol_addr); - if (it != addr_symbol_map_.end()) - return it->second; + const auto addr_it = addr_symbol_map_.find(symbol_addr); + if (addr_it != addr_symbol_map_.end()) + return addr_it->second; + else + { + const auto entry_it = entry_addr_symbol_map_.find(symbol_addr); + if (entry_it != entry_addr_symbol_map_.end()) + return entry_it->second; + } return empty_result; } @@ -197,6 +203,8 @@ symtab::load_(Elf* elf_handle, const bool is_kernel = elf_helpers::is_linux_kernel(elf_handle); std::unordered_set exported_kernel_symbols; + const bool is_ppc64 = elf_helpers::architecture_is_ppc64(elf_handle); + for (size_t i = 0; i < number_syms; ++i) { GElf_Sym *sym, sym_mem; @@ -304,6 +312,10 @@ symtab::load_(Elf* elf_handle, elf_helpers::maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle, sym); + if (is_ppc64 && symbol_sptr->is_function()) + update_function_entry_address_symbol_map(elf_handle, sym, + symbol_sptr); + const auto result = addr_symbol_map_.emplace(symbol_value, symbol_sptr); if (!result.second) @@ -364,5 +376,80 @@ symtab::load_(string_elf_symbols_map_sptr function_symbol_map, return true; } +void +symtab::update_function_entry_address_symbol_map( + Elf* elf_handle, + GElf_Sym* native_symbol, + const elf_symbol_sptr& symbol_sptr) +{ + + // For ppc64 ELFv1 binaries, we need to build a function entry point address + // -> function symbol map. This is in addition to the function pointer -> + // symbol map. This is because on ppc64 ELFv1, a function pointer is + // different from a function entry point address. + // + // On ppc64 ELFv1, the DWARF DIE of a function references the address of the + // entry point of the function symbol; whereas the value of the function + // symbol is the function pointer. As these addresses are different, if I we + // want to get to the symbol of a function from its entry point address (as + // referenced by DWARF function DIEs) we must have the two maps I mentionned + // right above. + // + // In other words, we need a map that associates a function entry point + // address with the symbol of that function, to be able to get the function + // symbol that corresponds to a given function DIE, on ppc64. + // + // The value of the function pointer (the value of the symbol) usually refers + // to the offset of a table in the .opd section. But sometimes, for a symbol + // named "foo", the corresponding symbol named ".foo" (note the dot before + // foo) which value is the entry point address of the function; that entry + // point address refers to a region in the .text section. + // + // So we are only interested in values of the symbol that are in the .opd + // section. + const GElf_Addr fn_desc_addr = native_symbol->st_value; + const GElf_Addr fn_entry_point_addr = + elf_helpers::lookup_ppc64_elf_fn_entry_point_address(elf_handle, + fn_desc_addr); + + const std::pair& result = + entry_addr_symbol_map_.emplace(fn_entry_point_addr, symbol_sptr); + + const addr_symbol_map_type::const_iterator it = result.first; + const bool was_inserted = result.second; + if (!was_inserted + && elf_helpers::address_is_in_opd_section(elf_handle, fn_desc_addr)) + { + // Either + // + // 'symbol' must have been registered as an alias for + // it->second->get_main_symbol() + // + // Or + // + // if the name of 'symbol' is foo, then the name of it2->second is + // ".foo". That is, foo is the name of the symbol when it refers to the + // function descriptor in the .opd section and ".foo" is an internal name + // for the address of the entry point of foo. + // + // In the latter case, we just want to keep a reference to "foo" as .foo + // is an internal name. + + const bool two_symbols_alias = + it->second->get_main_symbol()->does_alias(*symbol_sptr); + const bool symbol_is_foo_and_prev_symbol_is_dot_foo = + (it->second->get_name() == std::string(".") + symbol_sptr->get_name()); + + ABG_ASSERT(two_symbols_alias + || symbol_is_foo_and_prev_symbol_is_dot_foo); + + if (symbol_is_foo_and_prev_symbol_is_dot_foo) + // Let's just keep a reference of the symbol that the user sees in the + // source code (the one named foo). The symbol which name is prefixed + // with a "dot" is an artificial one. + entry_addr_symbol_map_[fn_entry_point_addr] = symbol_sptr; + } +} + } // end namespace symtab_reader } // end namespace abigail diff --git a/src/abg-symtab-reader.h b/src/abg-symtab-reader.h index 4c5e3b85c22d..2906bab818b0 100644 --- a/src/abg-symtab-reader.h +++ b/src/abg-symtab-reader.h @@ -251,12 +251,20 @@ private: typedef std::unordered_map addr_symbol_map_type; addr_symbol_map_type addr_symbol_map_; + /// Lookup map function entry address -> symbol + addr_symbol_map_type entry_addr_symbol_map_; + bool load_(Elf* elf_handle, ir::environment* env, symbol_predicate is_suppressed); bool load_(string_elf_symbols_map_sptr function_symbol_map, string_elf_symbols_map_sptr variables_symbol_map); + + void + update_function_entry_address_symbol_map(Elf* elf_handle, + GElf_Sym* native_symbol, + const elf_symbol_sptr& symbol_sptr); }; /// Helper class to allow range-for loops on symtabs for C++11 and later code.