1/* Standard libdwfl callbacks for debugging a live Linux process.
2   Copyright (C) 2005-2010, 2013, 2014 Red Hat, Inc.
3   This file is part of elfutils.
4
5   This file is free software; you can redistribute it and/or modify
6   it under the terms of either
7
8     * the GNU Lesser General Public License as published by the Free
9       Software Foundation; either version 3 of the License, or (at
10       your option) any later version
11
12   or
13
14     * the GNU General Public License as published by the Free
15       Software Foundation; either version 2 of the License, or (at
16       your option) any later version
17
18   or both in parallel, as here.
19
20   elfutils is distributed in the hope that it will be useful, but
21   WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23   General Public License for more details.
24
25   You should have received copies of the GNU General Public License and
26   the GNU Lesser General Public License along with this program.  If
27   not, see <http://www.gnu.org/licenses/>.  */
28
29#include "libdwflP.h"
30#include <inttypes.h>
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <errno.h>
34#include <stdio.h>
35#include <stdio_ext.h>
36#include <stdbool.h>
37#include <string.h>
38#include <stdlib.h>
39#include <fcntl.h>
40#include <unistd.h>
41#include <assert.h>
42#include <endian.h>
43#include "system.h"
44
45
46#define PROCMAPSFMT	"/proc/%d/maps"
47#define PROCMEMFMT	"/proc/%d/mem"
48#define PROCAUXVFMT	"/proc/%d/auxv"
49#define PROCEXEFMT	"/proc/%d/exe"
50
51
52/* Return ELFCLASS64 or ELFCLASS32 for the main ELF executable.  Return
53   ELFCLASSNONE for an error.  */
54
55static unsigned char
56get_pid_class (pid_t pid)
57{
58  char *fname;
59  if (asprintf (&fname, PROCEXEFMT, pid) < 0)
60    return ELFCLASSNONE;
61
62  int fd = open64 (fname, O_RDONLY);
63  free (fname);
64  if (fd < 0)
65    return ELFCLASSNONE;
66
67  unsigned char buf[EI_CLASS + 1];
68  ssize_t nread = pread_retry (fd, &buf, sizeof buf, 0);
69  close (fd);
70  if (nread != sizeof buf || buf[EI_MAG0] != ELFMAG0
71      || buf[EI_MAG1] != ELFMAG1 || buf[EI_MAG2] != ELFMAG2
72      || buf[EI_MAG3] != ELFMAG3
73      || (buf[EI_CLASS] != ELFCLASS64 && buf[EI_CLASS] != ELFCLASS32))
74    return ELFCLASSNONE;
75
76  return buf[EI_CLASS];
77}
78
79/* Search /proc/PID/auxv for the AT_SYSINFO_EHDR tag.
80
81   It would be easiest to call get_pid_class and parse everything according to
82   the 32-bit or 64-bit class.  But this would bring the overhead of syscalls
83   to open and read the "/proc/%d/exe" file.
84
85   Therefore this function tries to parse the "/proc/%d/auxv" content both
86   ways, as if it were the 32-bit format and also if it were the 64-bit format.
87   Only if it gives some valid data in both cases get_pid_class gets called.
88   In most cases only one of the format bit sizes gives valid data and the
89   get_pid_class call overhead can be saved.  */
90
91static int
92grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr)
93{
94  char *fname;
95  if (asprintf (&fname, PROCAUXVFMT, pid) < 0)
96    return ENOMEM;
97
98  int fd = open64 (fname, O_RDONLY);
99  free (fname);
100  if (fd < 0)
101    return errno == ENOENT ? 0 : errno;
102
103  GElf_Addr sysinfo_ehdr64 = 0;
104  GElf_Addr sysinfo_ehdr32 = 0;
105  GElf_Addr segment_align64 = dwfl->segment_align;
106  GElf_Addr segment_align32 = dwfl->segment_align;
107  off_t offset = 0;
108  ssize_t nread;
109  union
110  {
111    Elf64_auxv_t a64[64];
112    Elf32_auxv_t a32[128];
113  } d;
114  do
115    {
116      eu_static_assert (sizeof d.a64 == sizeof d.a32);
117      nread = pread_retry (fd, d.a64, sizeof d.a64, offset);
118      if (nread < 0)
119	{
120	  int ret = errno;
121	  close (fd);
122	  return ret;
123	}
124      for (size_t a32i = 0; a32i < nread / sizeof d.a32[0]; a32i++)
125	{
126	  const Elf32_auxv_t *a32 = d.a32 + a32i;
127	  switch (a32->a_type)
128	  {
129	    case AT_SYSINFO_EHDR:
130	      sysinfo_ehdr32 = a32->a_un.a_val;
131	      break;
132	    case AT_PAGESZ:
133	      segment_align32 = a32->a_un.a_val;
134	      break;
135	  }
136	}
137      for (size_t a64i = 0; a64i < nread / sizeof d.a64[0]; a64i++)
138	{
139	  const Elf64_auxv_t *a64 = d.a64 + a64i;
140	  switch (a64->a_type)
141	  {
142	    case AT_SYSINFO_EHDR:
143	      sysinfo_ehdr64 = a64->a_un.a_val;
144	      break;
145	    case AT_PAGESZ:
146	      segment_align64 = a64->a_un.a_val;
147	      break;
148	  }
149	}
150      offset += nread;
151    }
152  while (nread == sizeof d.a64);
153
154  close (fd);
155
156  bool valid64 = sysinfo_ehdr64 != 0 || segment_align64 != dwfl->segment_align;
157  bool valid32 = sysinfo_ehdr32 != 0 || segment_align32 != dwfl->segment_align;
158
159  unsigned char pid_class = ELFCLASSNONE;
160  if (valid64 && valid32)
161    pid_class = get_pid_class (pid);
162
163  if (pid_class == ELFCLASS64 || (valid64 && ! valid32))
164    {
165      *sysinfo_ehdr = sysinfo_ehdr64;
166      dwfl->segment_align = segment_align64;
167      return 0;
168    }
169  if (pid_class == ELFCLASS32 || (! valid64 && valid32))
170    {
171      *sysinfo_ehdr = sysinfo_ehdr32;
172      dwfl->segment_align = segment_align32;
173      return 0;
174    }
175  return ENOEXEC;
176}
177
178static int
179proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
180{
181  unsigned int last_dmajor = -1, last_dminor = -1;
182  uint64_t last_ino = -1;
183  char *last_file = NULL;
184  Dwarf_Addr low = 0, high = 0;
185
186  inline bool report (void)
187    {
188      if (last_file != NULL)
189	{
190	  Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, last_file,
191							 low, high);
192	  free (last_file);
193	  last_file = NULL;
194	  if (unlikely (mod == NULL))
195	    return true;
196	}
197      return false;
198    }
199
200  char *line = NULL;
201  size_t linesz;
202  ssize_t len;
203  while ((len = getline (&line, &linesz, f)) > 0)
204    {
205      if (line[len - 1] == '\n')
206	line[len - 1] = '\0';
207
208      Dwarf_Addr start, end, offset;
209      unsigned int dmajor, dminor;
210      uint64_t ino;
211      int nread = -1;
212      if (sscanf (line, "%" PRIx64 "-%" PRIx64 " %*s %" PRIx64
213		  " %x:%x %" PRIi64 " %n",
214		  &start, &end, &offset, &dmajor, &dminor, &ino, &nread) < 6
215	  || nread <= 0)
216	{
217	  free (line);
218	  return ENOEXEC;
219	}
220
221      /* If this is the special mapping AT_SYSINFO_EHDR pointed us at,
222	 report the last one and then this special one.  */
223      if (start == sysinfo_ehdr && start != 0)
224	{
225	  if (report ())
226	    {
227	    bad_report:
228	      free (line);
229	      return -1;
230	    }
231
232	  low = start;
233	  high = end;
234	  if (asprintf (&last_file, "[vdso: %d]", (int) pid) < 0
235	      || report ())
236	    goto bad_report;
237	}
238
239      char *file = line + nread + strspn (line + nread, " \t");
240      if (file[0] != '/' || (ino == 0 && dmajor == 0 && dminor == 0))
241	/* This line doesn't indicate a file mapping.  */
242	continue;
243
244      if (last_file != NULL
245	  && ino == last_ino && dmajor == last_dmajor && dminor == last_dminor)
246	{
247	  /* This is another portion of the same file's mapping.  */
248	  if (strcmp (last_file, file) != 0)
249	    goto bad_report;
250	  high = end;
251	}
252      else
253	{
254	  /* This is a different file mapping.  Report the last one.  */
255	  if (report ())
256	    goto bad_report;
257	  low = start;
258	  high = end;
259	  last_file = strdup (file);
260	  last_ino = ino;
261	  last_dmajor = dmajor;
262	  last_dminor = dminor;
263	}
264    }
265  free (line);
266
267  int result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC;
268
269  /* Report the final one.  */
270  bool lose = report ();
271
272  return result != 0 ? result : lose ? -1 : 0;
273}
274
275int
276dwfl_linux_proc_maps_report (Dwfl *dwfl, FILE *f)
277{
278  return proc_maps_report (dwfl, f, 0, 0);
279}
280INTDEF (dwfl_linux_proc_maps_report)
281
282int
283dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid)
284{
285  if (dwfl == NULL)
286    return -1;
287
288  /* We'll notice the AT_SYSINFO_EHDR address specially when we hit it.  */
289  GElf_Addr sysinfo_ehdr = 0;
290  int result = grovel_auxv (pid, dwfl, &sysinfo_ehdr);
291  if (result != 0)
292    return result;
293
294  char *fname;
295  if (asprintf (&fname, PROCMAPSFMT, pid) < 0)
296    return ENOMEM;
297
298  FILE *f = fopen (fname, "r");
299  free (fname);
300  if (f == NULL)
301    return errno;
302
303  (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
304
305  result = proc_maps_report (dwfl, f, sysinfo_ehdr, pid);
306
307  fclose (f);
308
309  return result;
310}
311INTDEF (dwfl_linux_proc_report)
312
313static ssize_t
314read_proc_memory (void *arg, void *data, GElf_Addr address,
315		  size_t minread, size_t maxread)
316{
317  const int fd = *(const int *) arg;
318  ssize_t nread = pread64 (fd, data, maxread, (off64_t) address);
319  /* Some kernels don't actually let us do this read, ignore those errors.  */
320  if (nread < 0 && (errno == EINVAL || errno == EPERM))
321    return 0;
322  if (nread > 0 && (size_t) nread < minread)
323    nread = 0;
324  return nread;
325}
326
327extern Elf *elf_from_remote_memory (GElf_Addr ehdr_vma,
328				    GElf_Xword pagesize,
329				    GElf_Addr *loadbasep,
330				    ssize_t (*read_memory) (void *arg,
331							    void *data,
332							    GElf_Addr address,
333							    size_t minread,
334							    size_t maxread),
335				    void *arg);
336
337
338/* Dwfl_Callbacks.find_elf */
339
340int
341dwfl_linux_proc_find_elf (Dwfl_Module *mod __attribute__ ((unused)),
342			  void **userdata __attribute__ ((unused)),
343			  const char *module_name, Dwarf_Addr base,
344			  char **file_name, Elf **elfp)
345{
346  int pid = -1;
347  if (module_name[0] == '/')
348    {
349      /* When this callback is used together with dwfl_linux_proc_report
350	 then we might see mappings of special character devices.  Make
351	 sure we only open and return regular files.  Special devices
352	 might hang on open or read.  (deleted) files are super special.
353	 The image might come from memory if we are attached.  */
354      struct stat sb;
355      if (stat (module_name, &sb) == -1 || (sb.st_mode & S_IFMT) != S_IFREG)
356	{
357	  if (strcmp (strrchr (module_name, ' ') ?: "", " (deleted)") == 0)
358	    pid = INTUSE(dwfl_pid) (mod->dwfl);
359	  else
360	    return -1;
361	}
362
363      if (pid == -1)
364	{
365	  int fd = open64 (module_name, O_RDONLY);
366	  if (fd >= 0)
367	    {
368	      *file_name = strdup (module_name);
369	      if (*file_name == NULL)
370		{
371		  close (fd);
372		  return ENOMEM;
373		}
374	    }
375	  return fd;
376	}
377    }
378
379  if (pid != -1 || sscanf (module_name, "[vdso: %d]", &pid) == 1)
380    {
381      /* Special case for in-memory ELF image.  */
382
383      bool detach = false;
384      bool tid_was_stopped = false;
385      struct __libdwfl_pid_arg *pid_arg = __libdwfl_get_pid_arg (mod->dwfl);
386      if (pid_arg != NULL && ! pid_arg->assume_ptrace_stopped)
387	{
388	  /* If any thread is already attached we are fine.  Read
389	     through that thread.  It doesn't have to be the main
390	     thread pid.  */
391	  pid_t tid = pid_arg->tid_attached;
392	  if (tid != 0)
393	    pid = tid;
394	  else
395	    detach = __libdwfl_ptrace_attach (pid, &tid_was_stopped);
396	}
397
398      char *fname;
399      if (asprintf (&fname, PROCMEMFMT, pid) < 0)
400	goto detach;
401
402      int fd = open64 (fname, O_RDONLY);
403      free (fname);
404      if (fd < 0)
405	goto detach;
406
407      *elfp = elf_from_remote_memory (base, getpagesize (), NULL,
408				      &read_proc_memory, &fd);
409
410      close (fd);
411
412      *file_name = NULL;
413
414    detach:
415      if (detach)
416	__libdwfl_ptrace_detach (pid, tid_was_stopped);
417      return -1;
418    }
419
420  return -1;
421}
422INTDEF (dwfl_linux_proc_find_elf)
423