159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath/* Find an ELF file for a module from its build ID. 2c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard Copyright (C) 2007-2010, 2014, 2015 Red Hat, Inc. 3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard This file is part of elfutils. 4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard This file is free software; you can redistribute it and/or modify 6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard it under the terms of either 7b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * the GNU Lesser General Public License as published by the Free 9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard Software Foundation; either version 3 of the License, or (at 10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard your option) any later version 11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard or 13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * the GNU General Public License as published by the Free 15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard Software Foundation; either version 2 of the License, or (at 16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard your option) any later version 17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard or both in parallel, as here. 19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard elfutils is distributed in the hope that it will be useful, but 21361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper WITHOUT ANY WARRANTY; without even the implied warranty of 22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper General Public License for more details. 24b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard You should have received copies of the GNU General Public License and 26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard the GNU Lesser General Public License along with this program. If 27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard not, see <http://www.gnu.org/licenses/>. */ 28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 2959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath#include "libdwflP.h" 3059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath#include <inttypes.h> 3159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath#include <fcntl.h> 32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <unistd.h> 33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 3559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathint 3659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathinternal_function 37df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard__libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name, 38df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard const size_t id_len, const uint8_t *id) 39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{ 40c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard /* We don't handle very short or really large build-ids. We need at 41c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard at least 3 and allow for up to 64 (normally ids are 20 long). */ 42c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard#define MIN_BUILD_ID_BYTES 3 43c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard#define MAX_BUILD_ID_BYTES 64 44c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard if (id_len < MIN_BUILD_ID_BYTES || id_len > MAX_BUILD_ID_BYTES) 45c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard { 46c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard __libdwfl_seterrno (DWFL_E_WRONG_ID_ELF); 47c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard return -1; 48c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard } 49c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard 5059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath /* Search debuginfo_path directories' .build-id/ subdirectories. */ 5159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 52c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard char id_name[sizeof "/.build-id/" + 1 + MAX_BUILD_ID_BYTES * 2 53c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard + sizeof ".debug" - 1]; 5459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath strcpy (id_name, "/.build-id/"); 5559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath int n = snprintf (&id_name[sizeof "/.build-id/" - 1], 5659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 4, "%02" PRIx8 "/", (uint8_t) id[0]); 5759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath assert (n == 3); 5859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath for (size_t i = 1; i < id_len; ++i) 59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 6059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath n = snprintf (&id_name[sizeof "/.build-id/" - 1 + 3 + (i - 1) * 2], 6159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 3, "%02" PRIx8, (uint8_t) id[i]); 6259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath assert (n == 2); 63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 6459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (debug) 6559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath strcpy (&id_name[sizeof "/.build-id/" - 1 + 3 + (id_len - 1) * 2], 6659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath ".debug"); 6759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 6859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath const Dwfl_Callbacks *const cb = mod->dwfl->callbacks; 69c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard char *path = strdup ((cb->debuginfo_path ? *cb->debuginfo_path : NULL) 70c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard ?: DEFAULT_DEBUGINFO_PATH); 71c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard if (path == NULL) 72c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard return -1; 73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 7459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath int fd = -1; 7559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath char *dir; 768aaf4fc46f5b0b1ed2b567734d06875a39047dd9Mark Wielaard char *paths = path; 778aaf4fc46f5b0b1ed2b567734d06875a39047dd9Mark Wielaard while (fd < 0 && (dir = strsep (&paths, ":")) != NULL) 78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 7959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (dir[0] == '+' || dir[0] == '-') 8059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath ++dir; 8159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 8259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath /* Only absolute directory names are useful to us. */ 8359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (dir[0] != '/') 8459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath continue; 8559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 8659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath size_t dirlen = strlen (dir); 8759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath char *name = malloc (dirlen + sizeof id_name); 8859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (unlikely (name == NULL)) 8959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath break; 9059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath memcpy (mempcpy (name, dir, dirlen), id_name, sizeof id_name); 9159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 923425454a10d307fae891fb667cf7969e945cde79Josh Stone fd = TEMP_FAILURE_RETRY (open (name, O_RDONLY)); 9359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (fd >= 0) 9459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 9559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (*file_name != NULL) 9659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath free (*file_name); 9759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath *file_name = canonicalize_file_name (name); 9859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (*file_name == NULL) 9959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 10059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath *file_name = name; 10159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath name = NULL; 10259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 10359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 10459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath free (name); 105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 107c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard free (path); 108c57829bb118bc30d874f7440b421abbebc74a733Mark Wielaard 1091d8bb25cac06b5af57f8733e5ea7a068a79edfe0Roland McGrath /* If we simply found nothing, clear errno. If we had some other error 1101d8bb25cac06b5af57f8733e5ea7a068a79edfe0Roland McGrath with the file, report that. Possibly this should treat other errors 1111d8bb25cac06b5af57f8733e5ea7a068a79edfe0Roland McGrath like ENOENT too. But ignoring all errors could mask some that should 1121d8bb25cac06b5af57f8733e5ea7a068a79edfe0Roland McGrath be reported. */ 1131d8bb25cac06b5af57f8733e5ea7a068a79edfe0Roland McGrath if (fd < 0 && errno == ENOENT) 1141d8bb25cac06b5af57f8733e5ea7a068a79edfe0Roland McGrath errno = 0; 1151d8bb25cac06b5af57f8733e5ea7a068a79edfe0Roland McGrath 11659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath return fd; 11759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath} 11859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 11959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathint 120df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaardinternal_function 121df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard__libdwfl_open_mod_by_build_id (Dwfl_Module *mod, bool debug, char **file_name) 122df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard{ 123df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard /* If *FILE_NAME was primed into the module, leave it there 124df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard as the fallback when we have nothing to offer. */ 125df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard errno = 0; 126df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard if (mod->build_id_len <= 0) 127df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard return -1; 128df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 129df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard const size_t id_len = mod->build_id_len; 130df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard const uint8_t *id = mod->build_id_bits; 131df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 132df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard return __libdwfl_open_by_build_id (mod, debug, file_name, id_len, id); 133df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard} 134df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 135df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaardint 13659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathdwfl_build_id_find_elf (Dwfl_Module *mod, 13759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath void **userdata __attribute__ ((unused)), 13859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath const char *modname __attribute__ ((unused)), 13959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath Dwarf_Addr base __attribute__ ((unused)), 14059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath char **file_name, Elf **elfp) 14159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath{ 14259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath *elfp = NULL; 143355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard if (mod->is_executable 144355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard && mod->dwfl->user_core != NULL 145355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard && mod->dwfl->user_core->executable_for_core != NULL) 146c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil { 147c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil /* When dwfl_core_file_report was called with a non-NULL executable file 148c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil name this callback will replace the Dwfl_Module main.name with the 1496097c00a539873e9baa22e10f9387b9c36c4fa25Jan Kratochvil recorded executable file when MOD was identified as main executable 1506097c00a539873e9baa22e10f9387b9c36c4fa25Jan Kratochvil (which then triggers opening and reporting of the executable). */ 151355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard const char *executable = mod->dwfl->user_core->executable_for_core; 152355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard int fd = open (executable, O_RDONLY); 153c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil if (fd >= 0) 154c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil { 155355b408bb9aa49703544fa4086e1ae463737fcf6Mark Wielaard *file_name = strdup (executable); 156c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil if (*file_name != NULL) 157c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil return fd; 158c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil else 159c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil close (fd); 160c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil } 161c53094634516313fb598d67e709f51f20d6acbbaJan Kratochvil } 162df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard int fd = __libdwfl_open_mod_by_build_id (mod, false, file_name); 16359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (fd >= 0) 16459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 165bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath Dwfl_Error error = __libdw_open_file (&fd, elfp, true, false); 166bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath if (error != DWFL_E_NOERROR) 167bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath __libdwfl_seterrno (error); 168bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath else if (__libdwfl_find_build_id (mod, false, *elfp) == 2) 169bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath { 170bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath /* This is a backdoor signal to short-circuit the ID refresh. */ 171bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath mod->main.valid = true; 172bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath return fd; 173bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath } 17459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath else 17559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 17659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath /* This file does not contain the ID it should! */ 17759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath elf_end (*elfp); 17859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath *elfp = NULL; 17959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath close (fd); 18059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath fd = -1; 18159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 182bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath free (*file_name); 183bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath *file_name = NULL; 18459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 185ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath else if (errno == 0 && mod->build_id_len > 0) 186ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath /* Setting this with no file yet loaded is a marker that 187ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath the build ID is authoritative even if we also know a 188ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath putative *FILE_NAME. */ 189ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath mod->main.valid = true; 190ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath 19159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath return fd; 192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 19359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathINTDEF (dwfl_build_id_find_elf) 194