125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Standard libdwfl callbacks for debugging a live Linux process. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2005-2010, 2013, 2014 Red Hat, Inc. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of either 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU Lesser General Public License as published by the Free 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 3 of the License, or (at 1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU General Public License as published by the Free 1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 2 of the License, or (at 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or both in parallel, as here. 1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received copies of the GNU General Public License and 2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the GNU Lesser General Public License along with this program. If 2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes not, see <http://www.gnu.org/licenses/>. */ 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libdwflP.h" 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <inttypes.h> 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/types.h> 3203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <sys/stat.h> 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <errno.h> 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio.h> 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio_ext.h> 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h> 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h> 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h> 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h> 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h> 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h> 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <endian.h> 4303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include "system.h" 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define PROCMAPSFMT "/proc/%d/maps" 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define PROCMEMFMT "/proc/%d/mem" 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define PROCAUXVFMT "/proc/%d/auxv" 4903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define PROCEXEFMT "/proc/%d/exe" 5003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 5103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 5203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Return ELFCLASS64 or ELFCLASS32 for the main ELF executable. Return 5303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ELFCLASSNONE for an error. */ 5403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 5503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic unsigned char 5603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesget_pid_class (pid_t pid) 5703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 5803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes char *fname; 5903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (asprintf (&fname, PROCEXEFMT, pid) < 0) 6003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return ELFCLASSNONE; 6103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 6203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int fd = open64 (fname, O_RDONLY); 6303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free (fname); 6403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (fd < 0) 6503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return ELFCLASSNONE; 6603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 6703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes unsigned char buf[EI_CLASS + 1]; 6803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ssize_t nread = pread_retry (fd, &buf, sizeof buf, 0); 6903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (fd); 7003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (nread != sizeof buf || buf[EI_MAG0] != ELFMAG0 7103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || buf[EI_MAG1] != ELFMAG1 || buf[EI_MAG2] != ELFMAG2 7203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || buf[EI_MAG3] != ELFMAG3 7303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || (buf[EI_CLASS] != ELFCLASS64 && buf[EI_CLASS] != ELFCLASS32)) 7403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return ELFCLASSNONE; 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return buf[EI_CLASS]; 7703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 7803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 7903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Search /proc/PID/auxv for the AT_SYSINFO_EHDR tag. 8003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 8103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes It would be easiest to call get_pid_class and parse everything according to 8203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the 32-bit or 64-bit class. But this would bring the overhead of syscalls 8303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes to open and read the "/proc/%d/exe" file. 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Therefore this function tries to parse the "/proc/%d/auxv" content both 8603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ways, as if it were the 32-bit format and also if it were the 64-bit format. 8703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Only if it gives some valid data in both cases get_pid_class gets called. 8803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes In most cases only one of the format bit sizes gives valid data and the 8903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes get_pid_class call overhead can be saved. */ 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 9225b3c049e70834cf33790a28643ab058b507b35cBen Chenggrovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr) 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *fname; 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (asprintf (&fname, PROCAUXVFMT, pid) < 0) 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return ENOMEM; 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int fd = open64 (fname, O_RDONLY); 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (fname); 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fd < 0) 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return errno == ENOENT ? 0 : errno; 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr sysinfo_ehdr64 = 0; 10403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr sysinfo_ehdr32 = 0; 10503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr segment_align64 = dwfl->segment_align; 10603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr segment_align32 = dwfl->segment_align; 10703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes off_t offset = 0; 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ssize_t nread; 10903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes union 11003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 11103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Elf64_auxv_t a64[64]; 11203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Elf32_auxv_t a32[128]; 11303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } d; 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes eu_static_assert (sizeof d.a64 == sizeof d.a32); 11703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes nread = pread_retry (fd, d.a64, sizeof d.a64, offset); 11803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (nread < 0) 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 12003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int ret = errno; 12103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (fd); 12203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return ret; 12303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 12403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes for (size_t a32i = 0; a32i < nread / sizeof d.a32[0]; a32i++) 12503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 12603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const Elf32_auxv_t *a32 = d.a32 + a32i; 12703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (a32->a_type) 12803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 12903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case AT_SYSINFO_EHDR: 13003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes sysinfo_ehdr32 = a32->a_un.a_val; 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 13203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case AT_PAGESZ: 13303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes segment_align32 = a32->a_un.a_val; 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 13503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 13603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 13703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes for (size_t a64i = 0; a64i < nread / sizeof d.a64[0]; a64i++) 13803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 13903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const Elf64_auxv_t *a64 = d.a64 + a64i; 14003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (a64->a_type) 14103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 14203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case AT_SYSINFO_EHDR: 14303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes sysinfo_ehdr64 = a64->a_un.a_val; 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 14503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case AT_PAGESZ: 14603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes segment_align64 = a64->a_un.a_val; 14703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 14803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes offset += nread; 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while (nread == sizeof d.a64); 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng close (fd); 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bool valid64 = sysinfo_ehdr64 != 0 || segment_align64 != dwfl->segment_align; 15703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bool valid32 = sysinfo_ehdr32 != 0 || segment_align32 != dwfl->segment_align; 15803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 15903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes unsigned char pid_class = ELFCLASSNONE; 16003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (valid64 && valid32) 16103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes pid_class = get_pid_class (pid); 16203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 16303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (pid_class == ELFCLASS64 || (valid64 && ! valid32)) 16403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 16503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *sysinfo_ehdr = sysinfo_ehdr64; 16603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl->segment_align = segment_align64; 16703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 0; 16803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 16903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (pid_class == ELFCLASS32 || (! valid64 && valid32)) 17003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 17103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *sysinfo_ehdr = sysinfo_ehdr32; 17203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl->segment_align = segment_align32; 17303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 0; 17403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 17503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return ENOEXEC; 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 17925b3c049e70834cf33790a28643ab058b507b35cBen Chengproc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid) 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int last_dmajor = -1, last_dminor = -1; 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint64_t last_ino = -1; 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *last_file = NULL; 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Addr low = 0, high = 0; 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline bool report (void) 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (last_file != NULL) 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, last_file, 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng low, high); 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (last_file); 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_file = NULL; 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (mod == NULL)) 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *line = NULL; 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t linesz; 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ssize_t len; 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((len = getline (&line, &linesz, f)) > 0) 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (line[len - 1] == '\n') 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng line[len - 1] = '\0'; 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Addr start, end, offset; 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int dmajor, dminor; 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint64_t ino; 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int nread = -1; 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sscanf (line, "%" PRIx64 "-%" PRIx64 " %*s %" PRIx64 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng " %x:%x %" PRIi64 " %n", 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng &start, &end, &offset, &dmajor, &dminor, &ino, &nread) < 6 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng || nread <= 0) 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (line); 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return ENOEXEC; 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If this is the special mapping AT_SYSINFO_EHDR pointed us at, 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng report the last one and then this special one. */ 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (start == sysinfo_ehdr && start != 0) 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (report ()) 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng bad_report: 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (line); 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng low = start; 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng high = end; 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (asprintf (&last_file, "[vdso: %d]", (int) pid) < 0 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng || report ()) 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto bad_report; 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *file = line + nread + strspn (line + nread, " \t"); 24003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (file[0] != '/' || (ino == 0 && dmajor == 0 && dminor == 0)) 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This line doesn't indicate a file mapping. */ 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (last_file != NULL 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ino == last_ino && dmajor == last_dmajor && dminor == last_dminor) 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is another portion of the same file's mapping. */ 24803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (strcmp (last_file, file) != 0) 24903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes goto bad_report; 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng high = end; 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is a different file mapping. Report the last one. */ 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (report ()) 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto bad_report; 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng low = start; 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng high = end; 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_file = strdup (file); 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_ino = ino; 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_dmajor = dmajor; 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_dminor = dminor; 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (line); 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng int result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC; 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Report the final one. */ 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool lose = report (); 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result != 0 ? result : lose ? -1 : 0; 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27525b3c049e70834cf33790a28643ab058b507b35cBen Chengint 27625b3c049e70834cf33790a28643ab058b507b35cBen Chengdwfl_linux_proc_maps_report (Dwfl *dwfl, FILE *f) 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return proc_maps_report (dwfl, f, 0, 0); 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 28025b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF (dwfl_linux_proc_maps_report) 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28225b3c049e70834cf33790a28643ab058b507b35cBen Chengint 28325b3c049e70834cf33790a28643ab058b507b35cBen Chengdwfl_linux_proc_report (Dwfl *dwfl, pid_t pid) 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dwfl == NULL) 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We'll notice the AT_SYSINFO_EHDR address specially when we hit it. */ 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr sysinfo_ehdr = 0; 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int result = grovel_auxv (pid, dwfl, &sysinfo_ehdr); 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (result != 0) 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *fname; 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (asprintf (&fname, PROCMAPSFMT, pid) < 0) 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return ENOMEM; 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng FILE *f = fopen (fname, "r"); 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (fname); 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (f == NULL) 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return errno; 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng (void) __fsetlocking (f, FSETLOCKING_BYCALLER); 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = proc_maps_report (dwfl, f, sysinfo_ehdr, pid); 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng fclose (f); 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 31125b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF (dwfl_linux_proc_report) 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic ssize_t 31425b3c049e70834cf33790a28643ab058b507b35cBen Chengread_proc_memory (void *arg, void *data, GElf_Addr address, 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t minread, size_t maxread) 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng const int fd = *(const int *) arg; 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ssize_t nread = pread64 (fd, data, maxread, (off64_t) address); 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Some kernels don't actually let us do this read, ignore those errors. */ 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nread < 0 && (errno == EINVAL || errno == EPERM)) 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nread > 0 && (size_t) nread < minread) 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng nread = 0; 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nread; 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32725b3c049e70834cf33790a28643ab058b507b35cBen Chengextern Elf *elf_from_remote_memory (GElf_Addr ehdr_vma, 32803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Xword pagesize, 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr *loadbasep, 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ssize_t (*read_memory) (void *arg, 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *data, 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr address, 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t minread, 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t maxread), 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *arg); 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Dwfl_Callbacks.find_elf */ 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34025b3c049e70834cf33790a28643ab058b507b35cBen Chengint 34125b3c049e70834cf33790a28643ab058b507b35cBen Chengdwfl_linux_proc_find_elf (Dwfl_Module *mod __attribute__ ((unused)), 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng void **userdata __attribute__ ((unused)), 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *module_name, Dwarf_Addr base, 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng char **file_name, Elf **elfp) 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 34603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int pid = -1; 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (module_name[0] == '/') 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 34903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* When this callback is used together with dwfl_linux_proc_report 35003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes then we might see mappings of special character devices. Make 35103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes sure we only open and return regular files. Special devices 35203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes might hang on open or read. (deleted) files are super special. 35303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes The image might come from memory if we are attached. */ 35403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct stat sb; 35503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (stat (module_name, &sb) == -1 || (sb.st_mode & S_IFMT) != S_IFREG) 35603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 35703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (strcmp (strrchr (module_name, ' ') ?: "", " (deleted)") == 0) 35803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes pid = INTUSE(dwfl_pid) (mod->dwfl); 35903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 36003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 36103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 36203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 36303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (pid == -1) 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 36503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int fd = open64 (module_name, O_RDONLY); 36603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (fd >= 0) 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 36803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *file_name = strdup (module_name); 36903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (*file_name == NULL) 37003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 37103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (fd); 37203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return ENOMEM; 37303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return fd; 37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (pid != -1 || sscanf (module_name, "[vdso: %d]", &pid) == 1) 38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Special case for in-memory ELF image. */ 38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bool detach = false; 38403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bool tid_was_stopped = false; 38503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct __libdwfl_pid_arg *pid_arg = __libdwfl_get_pid_arg (mod->dwfl); 38603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (pid_arg != NULL && ! pid_arg->assume_ptrace_stopped) 38703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 38803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* If any thread is already attached we are fine. Read 38903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes through that thread. It doesn't have to be the main 39003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes thread pid. */ 39103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes pid_t tid = pid_arg->tid_attached; 39203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tid != 0) 39303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes pid = tid; 39403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 39503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes detach = __libdwfl_ptrace_attach (pid, &tid_was_stopped); 39603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 39703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *fname; 39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (asprintf (&fname, PROCMEMFMT, pid) < 0) 40003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes goto detach; 40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int fd = open64 (fname, O_RDONLY); 40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (fname); 40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fd < 0) 40503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes goto detach; 40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *elfp = elf_from_remote_memory (base, getpagesize (), NULL, 40803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &read_proc_memory, &fd); 40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng close (fd); 41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng *file_name = NULL; 41303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 41403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes detach: 41503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (detach) 41603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libdwfl_ptrace_detach (pid, tid_was_stopped); 41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 42225b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF (dwfl_linux_proc_find_elf) 423