From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from seahorse.cherry.relay.mailchannels.net (seahorse.cherry.relay.mailchannels.net [23.83.223.161]) by sourceware.org (Postfix) with ESMTPS id 490FA3858D1E for ; Fri, 22 Mar 2024 20:18:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 490FA3858D1E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=ascii.art.br Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=ascii.art.br ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 490FA3858D1E Authentication-Results: server2.sourceware.org; arc=pass smtp.remote-ip=23.83.223.161 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1711138694; cv=pass; b=uuGuL/e/C3QMh992LX9RPzfh2DwBL7tZW2OXhH/ZFGew/rM7Ia3LppNDQpGtULolcDbSpG6Tzg2nrfabAKoWNoVxSe5Eo/YmWt/I9S3XqkJd/efcdibYbipBmSoAlS1Xvs9bp1/iyw4rRGvOpNRlmWmbcMQzCfKbLXSfVg1FlE0= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1711138694; c=relaxed/simple; bh=zO0xeMxAv0IkdktayQpLAuA7G+K6hv7gMPyPfOYexgI=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=wHU5vICGtk66am1DLsOaMigeOAPse0ezSM5m01jXEho6C86h05bXIgHUP6RQJTXrWApfK5y9RYws8xYyCA6j+deQpEMF8+W3sl3XUbwAqPSKiCebp4oi/0YN85ZT+WBzAbSMiGd63UjH6gv16miQoVYJ3k4wPrfVY9UX2t3vu50= ARC-Authentication-Results: i=2; server2.sourceware.org X-Sender-Id: dreamhost|x-authsender|tuliom@ascii.art.br Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id CB00742838; Fri, 22 Mar 2024 20:18:01 +0000 (UTC) Received: from pdx1-sub0-mail-a310.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id 2C55E42E26; Fri, 22 Mar 2024 20:18:01 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1711138681; a=rsa-sha256; cv=none; b=F4zjIF/eNYYoPIzbLuW8RYCnHMrSUNBOUX74LOFfFO4pVQYH2iDS/nKl2Q/tJ2OnWc0qAL 3Sn37Jlkh4evRrosWYhpQh21FMowPpjK0wSSzO3kt93daTCBBbHI+HESf5Z3G+yF7dX9Ug 58saDsOzVG3WIZ3hrSFz4yO4RGYTEvjZkt/DKuxpq6K0bWKyBXBQOHI+5YJ4zxUOJBJq4O DCEnVZutkaTgsVD8KOnrW0xBMfmTcLqWnOPUy+HKRpBl/14roKOasXcmHJqzLO3iucu2+u MdT9Jepyj8qbRapHb+Pz3j/KRbuYTg3ND8yo53XTEsFeDtlkwZvgA2VjVAJIzA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1711138681; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=EEE18zc5j1vnNu8db02kEla2dFuRlxxEI1sUaHz3Vog=; b=DUF4cA9bMhKp2/E3RnzWY7prLXxEBgGfh/5r0FFAEKwE2weIk6Wy1Q/LH7t03iIDt0d/+/ XikGvehoue3fbosrfftMY12qcVX0RJqiXGIuFDP4glELFRnuo+weYKJAb/kuzbo7St43OU TUPacjTZwYtGOtUx/VN8g9E5KFCbo4ybfGSv3XXYg4BFkQEGU+bUSsZADeZ54Dit5737WM t1hbMwLz4DieJgBVvPuTXL2/XpX4jm2xNNABvG4pHRZaFqapxRU+SH7Mh3cGu3OQAAGFiD mwBz85Q7fHUXpjpkIA6OnxuM2vtILXnnXYZIpmTox9ZEJK9OkIBLSb8zHaFong== ARC-Authentication-Results: i=1; rspamd-6c65898bb7-7jk9s; auth=pass smtp.auth=dreamhost smtp.mailfrom=tuliom@ascii.art.br X-Sender-Id: dreamhost|x-authsender|tuliom@ascii.art.br X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|tuliom@ascii.art.br X-MailChannels-Auth-Id: dreamhost X-Macabre-Army: 6634068402bf642a_1711138681452_2023160835 X-MC-Loop-Signature: 1711138681452:3386365748 X-MC-Ingress-Time: 1711138681452 Received: from pdx1-sub0-mail-a310.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.99.189.244 (trex/6.9.2); Fri, 22 Mar 2024 20:18:01 +0000 Received: from ascii.art.br (ip-191-5-87-27.isp.valenet.com.br [191.5.87.27]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: tuliom@ascii.art.br) by pdx1-sub0-mail-a310.dreamhost.com (Postfix) with ESMTPSA id 4V1YY44Rx1z7F; Fri, 22 Mar 2024 13:18:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ascii.art.br; s=dreamhost; t=1711138681; bh=EEE18zc5j1vnNu8db02kEla2dFuRlxxEI1sUaHz3Vog=; h=From:To:Cc:Subject:Date:Content-Transfer-Encoding; b=RibIf6535l2SOYmusUdlOmcSFNq6LXVglNt+6h7UT7oJ4stTN45aw2gWM0noFpgZz 6AsBMQj3UWi8Vtu1K4B3A/KTRHeYin+LUDdD4gf5Fc6b/3dTi049MUnY0H52XLfEe/ l9BtD9nzk2eFWrHiIr5aeeA9cMRwsJXE3x2fLHKETyoS/sI+DlJnpryKU9nBJ4S1Vi 1kgZCCyo75H9ylqEljF14NcbIUPO8Yfm55ZuYhVrty4+qSW4Rag/3Fflaf4IW+XGJh ftvzhIIJwDTDgTVuk3exn5o/zM83RjcNPOjs0yPDL5kjCo2uMSuLWQUANadWeF0824 74qaETQF3n6AQ== From: Tulio Magno Quites Machado Filho To: annobin@sourceware.org Cc: grant@hcubed.com, Nick Clifton Subject: [PATCH] Add support for global-file-syms to the clang and llvm plugins Date: Fri, 22 Mar 2024 17:17:36 -0300 Message-ID: <20240322201736.421134-1-tuliom@ascii.art.br> X-Mailer: git-send-email 2.44.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-8.3 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_BARRACUDACENTRAL,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Tulio Magno Quites Machado Filho This part starts by moving the implementation of parse_env() to annobin-common.cc in order to be shared between the gcc and the llvm plugins. This was required because the llvm plugin didn't have a mechanism to receive arguments from the user. This commit adds support for using the environment variable ANNOBIN for the LLVM plugin, although it's still missing many of the basic features available in the other plugins. Both clang and llvm plugins are now able to generate the same output as the GCC plugin, e.g. _annobin_hello_c_1711138217_00204218_start. --- annobin-common.cc | 61 ++++++++++++++++++++++++++++++++++++++++ annobin-common.h | 19 +++++++++++++ clang-plugin/Makefile.in | 12 +++++++- clang-plugin/annobin.cpp | 45 +++++++++++++++++++++++++---- gcc-plugin/Makefile.am | 2 +- gcc-plugin/Makefile.in | 7 +++-- gcc-plugin/annobin.cc | 45 ++--------------------------- llvm-plugin/Makefile.in | 21 ++++++++++++-- llvm-plugin/annobin.cpp | 53 ++++++++++++++++++++++++++++++++-- 9 files changed, 208 insertions(+), 57 deletions(-) create mode 100644 annobin-common.cc create mode 100644 annobin-common.h diff --git a/annobin-common.cc b/annobin-common.cc new file mode 100644 index 0000000..bbdba41 --- /dev/null +++ b/annobin-common.cc @@ -0,0 +1,61 @@ +/* annobin - Common functions used by plugins. + Copyright (c) 2024 Red Hat. + + This 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, or (at your + option) any later version. + + It 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. */ + +#include "annobin-common.h" + +#include +#include + +extern bool parse_argument (const char *, const char *); + +void +parse_env (bool (* parse_argument)(const char *, const char *)) +{ + char arg[2048]; + const char * env; + + if ((env = getenv ("ANNOBIN")) == NULL) + return; + + while (*env != 0) + { + const char * comma; + + comma = strchr (env, ','); + if (comma) + { + strncpy (arg, env, comma - env); + arg[comma - env] = 0; + env = comma + 1; + } + else + { + strncpy (arg, env, sizeof arg - 1); + arg[sizeof arg - 1] = 0; + env += strlen (env); + } + + char * value = strchr (arg, '='); + if (value) + { + * value = 0; + value ++; + } + else + { + value = (char *) ""; + } + + (void) (*parse_argument) (arg, value); + } +} diff --git a/annobin-common.h b/annobin-common.h new file mode 100644 index 0000000..8007c6c --- /dev/null +++ b/annobin-common.h @@ -0,0 +1,19 @@ +/* annobin - Common functions used by plugins. + Copyright (c) 2024 Red Hat. + + This 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, or (at your + option) any later version. + + It 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. */ +#ifndef ANNOBIN_COMMON_H_ +#define ANNOBIN_COMMON_H_ + +#include + +void parse_env (bool (* parse_argument)(const char *, const char *)); +#endif // ANNOBIN-COMMON_H_ diff --git a/clang-plugin/Makefile.in b/clang-plugin/Makefile.in index 1fc45c0..9ceba39 100644 --- a/clang-plugin/Makefile.in +++ b/clang-plugin/Makefile.in @@ -65,7 +65,9 @@ PLUGIN_TEST_OPTIONS = \ # -flto # Not used because the object file generated is not an ELF format file. # -fcf-protection # Not used because not supported by all architectures -check: @srcdir@/hello.c $(PLUGIN_NAME) +TESTS = test-global-file-syms + +check: @srcdir@/hello.c $(PLUGIN_NAME) $(addsuffix .log,$(TESTS)) $(CLANG) -fplugin=$(PLUGIN) $(PLUGIN_TEST_OPTIONS) -c @srcdir@/hello.c $(READELF) --wide --notes hello.o > clang-plugin-test.readelf.out @ grep --silent -e "annobin built by clang version" clang-plugin-test.readelf.out @@ -74,3 +76,11 @@ check: @srcdir@/hello.c $(PLUGIN_NAME) @ grep --silent -e "SpecLoadHarden" clang-plugin-test.readelf.out $(ANNOCHECK) --skip-all --test-optimization --test-fortify --test-stack-prot hello.o --verbose @ echo "PASS Clang plugin test" + +test-global-file-syms.log: @srcdir@/hello.c $(PLUGIN_NAME) + $(CLANG) -fplugin=$(PLUGIN) -fplugin-arg-annobin-global-file-syms -c $< -o test-global-file-syms.o + $(READELF) --wide --syms test-global-file-syms.o > test-global-file-syms.readelf.out + @ grep --silent -e "_annobin.\+_hello_c_" test-global-file-syms.readelf.out + @ grep --silent -e '_annobin.\+_hello_c_.\+_start' test-global-file-syms.readelf.out + @ grep --silent -e '_annobin.\+_hello_c_.\+_end' test-global-file-syms.readelf.out + @ echo "PASS Clang global-file-syms test" | tee $@ diff --git a/clang-plugin/annobin.cpp b/clang-plugin/annobin.cpp index 5426d22..6e1a8d4 100644 --- a/clang-plugin/annobin.cpp +++ b/clang-plugin/annobin.cpp @@ -31,12 +31,19 @@ using namespace llvm; #include #include #include +#include #include +#include namespace { static const unsigned int annobin_version = (unsigned int) (ANNOBIN_VERSION * 100); bool be_verbose = false; + /* True if the symbols used to map addresses to file names should be global. + On some architectures these symbols have to be global so that they will + be preserved in object files. But doing so can prevent the build-id + mechanism from working, since the symbols contain build-date information. */ + bool global_file_name_symbols = false; // Helper functions used throughout this file. template @@ -188,6 +195,30 @@ private: for( auto & c : name) if (!isalnum (c)) c = '_'; + + if (global_file_name_symbols) + { + /* A program can have multiple source files with the same name. + Or indeed the same source file can be included multiple times. + Or a library can be built from a sources which include file names + that match application file names. Whatever the reason, we need + to be ensure that we generate unique global symbol names. So we + append the time to the symbol name. This will of course break + the functionality of build-ids. That is why this option is off + by default. */ + struct timeval tv; + + if (gettimeofday (& tv, NULL)) + { + ice ("unable to get time of day."); + tv.tv_sec = tv.tv_usec = 0; + } + std::ostringstream t; + t << "_" << std::setfill('0') << std::setw(8) << (long) tv.tv_sec; + t << "_" << std::setfill('0') << std::setw(8) << (long) tv.tv_usec; + name += t.str(); + } + } void @@ -574,11 +605,13 @@ private: { if (args[i] == "help") inform ("supported options:\n\ - help Display this message\n\ - disable Disable the plugin\n\ - enable Reenable the plugin if it has been disabled\n\ - version Displays the version number\n\ - verbose Produce descriptive messages whilst working"); + help Display this message\n\ + disable Disable the plugin\n\ + enable Reenable the plugin if it has been disabled\n\ + version Displays the version number\n\ + verbose Produce descriptive messages whilst working\n\ + \n\ + global-file-syms Create final name symbols that are global"); else if (args[i] == "disable") enabled = false; else if (args[i] == "enable") @@ -587,6 +620,8 @@ private: inform ("Annobin plugin version: %u", annobin_version); else if (args[i] == "verbose") be_verbose = true; + else if (args[i] == "global-file-syms") + global_file_name_symbols = true; else inform ("error: unknown option: %s", args[i].c_str()); } diff --git a/gcc-plugin/Makefile.am b/gcc-plugin/Makefile.am index eca5e10..9616018 100644 --- a/gcc-plugin/Makefile.am +++ b/gcc-plugin/Makefile.am @@ -8,7 +8,7 @@ plugin_LTLIBRARIES = annobin.la AM_CPPFLAGS = -I'$(top_builddir)' -I'$(top_srcdir)' AUTOMAKE_OPTIONS = no-dependencies -annobin_la_SOURCES = annobin.cc +annobin_la_SOURCES = annobin.cc ../annobin-common.cc EXTRA_annobin_la_SOURCES = aarch64.annobin.cc arm.annobin.cc dummy.annobin.cc powerpc.annobin.cc s390.annobin.cc x86_64.annobin.cc i686.annobin.cc riscv.annobin.cc mips.annobin.cc annobin_la_LIBADD = @target_plugin@ annobin_la_DEPENDENCIES = @target_plugin@ diff --git a/gcc-plugin/Makefile.in b/gcc-plugin/Makefile.in index d5604cc..6ecc51f 100644 --- a/gcc-plugin/Makefile.in +++ b/gcc-plugin/Makefile.in @@ -144,7 +144,7 @@ am__uninstall_files_from_dir = { \ } am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(plugin_LTLIBRARIES) -am_annobin_la_OBJECTS = annobin.lo +am_annobin_la_OBJECTS = annobin.lo annobin-common.lo annobin_la_OBJECTS = $(am_annobin_la_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) @@ -347,7 +347,7 @@ top_srcdir = @top_srcdir@ plugin_LTLIBRARIES = annobin.la AM_CPPFLAGS = -I'$(top_builddir)' -I'$(top_srcdir)' AUTOMAKE_OPTIONS = no-dependencies -annobin_la_SOURCES = annobin.cc +annobin_la_SOURCES = annobin.cc ../annobin-common.cc EXTRA_annobin_la_SOURCES = aarch64.annobin.cc arm.annobin.cc dummy.annobin.cc powerpc.annobin.cc s390.annobin.cc x86_64.annobin.cc i686.annobin.cc riscv.annobin.cc mips.annobin.cc annobin_la_LIBADD = @target_plugin@ annobin_la_DEPENDENCIES = @target_plugin@ @@ -460,6 +460,9 @@ distclean-compile: .cc.lo: $(AM_V_CXX)$(LTCXXCOMPILE) -c -o $@ $< +annobin-common.lo: ../annobin-common.cc + $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o annobin-common.lo `test -f '../annobin-common.cc' || echo '$(srcdir)/'`../annobin-common.cc + mostlyclean-libtool: -rm -f *.lo diff --git a/gcc-plugin/annobin.cc b/gcc-plugin/annobin.cc index 440029e..af1e2dd 100644 --- a/gcc-plugin/annobin.cc +++ b/gcc-plugin/annobin.cc @@ -16,6 +16,7 @@ #include #include +#include "annobin-common.h" #include "annobin-global.h" #include "annobin.h" @@ -3123,43 +3124,6 @@ parse_args (unsigned argc, struct plugin_argument * argv) return result; } -static void -parse_env (const char * env) -{ - while (*env != 0) - { - const char * comma; - char * arg = annobin_note_buffer; - - comma = strchr (env, ','); - if (comma) - { - strncpy (arg, env, comma - env); - arg[comma - env] = 0; - env = comma + 1; - } - else - { - strncpy (arg, env, sizeof annobin_note_buffer - 1); - arg[sizeof annobin_note_buffer - 1] = 0; - env += strlen (env); - } - - char * value = strchr (arg, '='); - if (value) - { - * value = 0; - value ++; - } - else - { - value = (char *) ""; - } - - (void) parse_argument (arg, value); - } -} - int plugin_init (struct plugin_name_args * plugin_info, struct plugin_gcc_version * version) @@ -3173,12 +3137,7 @@ plugin_init (struct plugin_name_args * plugin_info, return 1; } - const char * env; - if ((env = getenv ("ANNOBIN")) != NULL) - { - parse_env (env); - } - + parse_env (&parse_argument); if (plugins_active_p () && (annobin_extra_prefix[0] == 0)) { /* See BZ 2162746 for an example of why this is needed. */ diff --git a/llvm-plugin/Makefile.in b/llvm-plugin/Makefile.in index bcee371..f9b4e26 100644 --- a/llvm-plugin/Makefile.in +++ b/llvm-plugin/Makefile.in @@ -28,10 +28,15 @@ PLUGIN_NAME = annobin-for-llvm.so all: $(PLUGIN_NAME) Makefile -$(PLUGIN_NAME): annobin.cpp +$(PLUGIN_NAME): annobin.cpp annobin-common.o clang++ $(CLANG_TARGET_OPTIONS) $(LLVM_CXX_OPTIONS) \ $(PLUGIN_OPTIONS) $(LLVM_LD_OPTIONS) $(LLVM_SYS_LIBS) \ - -I .. -I$(INCDIR) $< -o $@ + -I .. -I$(INCDIR) $^ -o $@ + +annobin-common.o: @top_srcdir@/annobin-common.cc + clang++ -c $(CLANG_TARGET_OPTIONS) $(LLVM_CXX_OPTIONS) \ + $(PLUGIN_OPTIONS) $(LLVM_LD_OPTIONS) $(LLVM_SYS_LIBS) \ + -I .. -I$(INCDIR) $^ -o $@ install: $(PLUGIN_NAME) install -Dpm0755 -t ${PLUGIN_INSTALL_DIR} $< @@ -63,6 +68,8 @@ PLUGIN_TEST_OPTIONS = \ # -flto # Not used because the object file generated is not an ELF format file. # -fcf-protection # Not used because not supported by all architectures +TESTS = test-global-file-syms + check: $(PLUGIN_NAME) @ if [ `echo | clang -dM -E - | grep __clang_major__ | cut -f 3 -d ' '` -gt 14 ] ; \ then \ @@ -85,7 +92,7 @@ check-newpm: check-pre-clang-13: $(MAKE) check-run LOAD_PLUGIN_ARG="-Xclang -load -Xclang $(PLUGIN)" -check-run: @srcdir@/hello.c +check-run: @srcdir@/hello.c $(addsuffix .log,$(TESTS)) echo Compiling with $(LOAD_PLUGIN_ARG) ... $(CLANG) $(LOAD_PLUGIN_ARG) $(PLUGIN_TEST_OPTIONS) -c @srcdir@/hello.c echo Checking with readelf ... @@ -97,3 +104,11 @@ check-run: @srcdir@/hello.c $(ANNOCHECK) --skip-all --test-optimization --test-fortify --test-stack-prot hello.o || : $(ANNOCHECK) --skip-all --test-optimization --test-fortify --test-stack-prot hello.o echo "PASS LLVM plugin test [$(LOAD_PLUGIN_ARG)]" + +test-global-file-syms.log: @srcdir@/hello.c + ANNOBIN=global-file-syms $(CLANG) $(LOAD_PLUGIN_ARG) -c $< -o test-global-file-syms.o + $(READELF) --wide --syms test-global-file-syms.o > test-global-file-syms.readelf.out + @ grep --silent -e "_annobin.\+_hello_c_" test-global-file-syms.readelf.out + @ grep --silent -e '_annobin.\+_hello_c_.\+_start' test-global-file-syms.readelf.out + @ grep --silent -e '_annobin.\+_hello_c_.\+_end' test-global-file-syms.readelf.out + @ echo "PASS LLVM global-file-syms test" | tee $@ diff --git a/llvm-plugin/annobin.cpp b/llvm-plugin/annobin.cpp index fe3e036..08b6241 100644 --- a/llvm-plugin/annobin.cpp +++ b/llvm-plugin/annobin.cpp @@ -25,16 +25,24 @@ #endif #include "llvm/LTO/legacy/LTOCodeGenerator.h" #include "annobin-global.h" +#include "annobin-common.h" #include #include #include +#include #include +#include using namespace llvm; namespace { static bool be_verbose = false; static unsigned int target_start_sym_bias = 0; + /* True if the symbols used to map addresses to file names should be global. + On some architectures these symbols have to be global so that they will + be preserved in object files. But doing so can prevent the build-id + mechanism from working, since the symbols contain build-date information. */ + bool global_file_name_symbols = false; // Helper functions used throughout this file. template @@ -46,7 +54,6 @@ namespace (void) std::initializer_list{((oss << args), 1)...}; return strdup (oss.str().c_str()); } -#if 0 static inline void inform (char const fmt[], ...) { @@ -59,7 +66,6 @@ namespace fputc ('\n', stderr); va_end (args); } -#endif static inline void verbose (char const fmt[], ...) { @@ -278,6 +284,24 @@ namespace free (buffer); } + static bool + parse_argument (const char * key, const char * value) + { + if (streq (key, "verbose")) + be_verbose = true; + else if (streq (key, "global-file-syms")) + global_file_name_symbols = true; + else if (streq (key, "no-global-file-syms")) + global_file_name_symbols = false; + else + { + inform ("annobin: unrecognised option: %s\n", key); + return false; + } + + return true; + } + public: #if __clang_major__ > 12 AnnobinModule() @@ -289,6 +313,8 @@ namespace if (getenv ("ANNOBIN_VERBOSE") != NULL && ! streq (getenv ("ANNOBIN_VERBOSE"), "false")) be_verbose = true; + + parse_env (&parse_argument); } void @@ -486,6 +512,29 @@ namespace for( auto & c : name) if (!isalnum (c)) c = '_'; + + if (global_file_name_symbols) + { + /* A program can have multiple source files with the same name. + Or indeed the same source file can be included multiple times. + Or a library can be built from a sources which include file names + that match application file names. Whatever the reason, we need + to be ensure that we generate unique global symbol names. So we + append the time to the symbol name. This will of course break + the functionality of build-ids. That is why this option is off + by default. */ + struct timeval tv; + + if (gettimeofday (& tv, NULL)) + { + ice ("unable to get time of day."); + tv.tv_sec = tv.tv_usec = 0; + } + std::ostringstream t; + t << "_" << std::setfill('0') << std::setw(8) << (long) tv.tv_sec; + t << "_" << std::setfill('0') << std::setw(8) << (long) tv.tv_usec; + name += t.str(); + } } static void -- 2.44.0