Coverage Report

Created: 2026-07-25 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libunwind/src/os-linux.c
Line
Count
Source
1
/* libunwind - a platform-independent unwind library
2
   Copyright (C) 2003-2005 Hewlett-Packard Co
3
        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5
This file is part of libunwind.
6
7
Permission is hereby granted, free of charge, to any person obtaining
8
a copy of this software and associated documentation files (the
9
"Software"), to deal in the Software without restriction, including
10
without limitation the rights to use, copy, modify, merge, publish,
11
distribute, sublicense, and/or sell copies of the Software, and to
12
permit persons to whom the Software is furnished to do so, subject to
13
the following conditions:
14
15
The above copyright notice and this permission notice shall be
16
included in all copies or substantial portions of the Software.
17
18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25
26
#include <limits.h>
27
#include <stdio.h>
28
#include <sys/stat.h>
29
#include <string.h>
30
#include <stdlib.h>
31
#include <assert.h>
32
33
#include "libunwind_i.h"
34
#include "os-linux.h"
35
36
#ifndef MAX_VDSO_SIZE
37
/*Dont know what is the Max Size in my system it was 8192 or twice the page size*/
38
0
# define MAX_VDSO_SIZE ((size_t) 2 * sysconf (_SC_PAGESIZE))
39
#endif
40
41
#ifndef MAP_32BIT
42
# define MAP_32BIT 0
43
#endif
44
45
46
int
47
tdep_get_elf_image (unw_addr_space_t as, struct elf_image *ei, pid_t pid, unw_word_t ip,
48
                    unsigned long *segbase, unsigned long *mapoff,
49
                    char *path, size_t pathlen,
50
                    void *arg)
51
29.5k
{
52
29.5k
  struct map_iterator mi;
53
29.5k
  int found = 0, rc = UNW_ESUCCESS;
54
29.5k
  unsigned long hi;
55
29.5k
  char root[sizeof ("/proc/0123456789/root")], *cp;
56
29.5k
  char *full_path;
57
29.5k
  struct stat st;
58
29.5k
  unw_accessors_t *a;
59
29.5k
  unw_word_t magic;
60
61
62
29.5k
  if (maps_init (&mi, pid) < 0)
63
0
    return -1;
64
65
103k
  while (maps_next (&mi, segbase, &hi, mapoff, NULL))
66
103k
    if (ip >= *segbase && ip < hi)
67
29.5k
      {
68
29.5k
        found = 1;
69
29.5k
        break;
70
29.5k
      }
71
72
29.5k
  if (!found)
73
0
    {
74
0
      maps_close (&mi);
75
0
      return -1;
76
0
    }
77
78
  // get path only, no need to map elf image
79
29.5k
  if (!ei && path)
80
0
    {
81
0
      strncpy(path, mi.path, pathlen);
82
0
      path[pathlen - 1] = '\0';
83
0
      if (strlen(mi.path) >= pathlen)
84
0
        rc = -UNW_ENOMEM;
85
86
0
      maps_close (&mi);
87
0
      return rc;
88
0
    }
89
90
29.5k
  full_path = mi.path;
91
92
  /* Get process root */
93
29.5k
  memcpy (root, "/proc/", 6);
94
29.5k
  cp = unw_ltoa (root + 6, pid);
95
29.5k
  assert (cp + 6 < root + sizeof (root));
96
29.5k
  memcpy (cp, "/root", 6);
97
98
29.5k
  size_t _len = strlen (mi.path) + 1;
99
29.5k
  if (!stat(root, &st) && S_ISDIR(st.st_mode))
100
29.5k
    _len += strlen (root);
101
0
  else
102
0
    root[0] = '\0';
103
104
29.5k
  full_path = path;
105
29.5k
  if(!path)
106
0
    full_path = (char*) malloc (_len);
107
29.5k
  else if(_len >= pathlen) // passed buffer is too small, fail
108
0
    {
109
0
      maps_close (&mi);
110
0
      return -1;
111
0
    }
112
113
29.5k
  strcpy (full_path, root);
114
29.5k
  strcat (full_path, mi.path);
115
116
29.5k
  if (stat(full_path, &st) || !S_ISREG(st.st_mode))
117
0
    strcpy(full_path, mi.path);
118
119
29.5k
  rc = elf_map_image (ei, full_path);
120
121
  /*Follwing code is adapted from 
122
    https://sourceware.org/pipermail/frysk-cvs/2008q1/007245.html,
123
    For VDSO there is no file in the file system, so read the ELF , 
124
    and create mmaped file for the content of the VDSO 
125
  */
126
29.5k
  if (rc != -1)
127
29.5k
  {
128
29.5k
    maps_close (&mi);
129
29.5k
    goto err_exit;
130
29.5k
  }
131
132
  /* If the above failed, try to bring in page-sized segments directly
133
     from process memory.  This enables us to locate VDSO unwind
134
     tables.  */
135
0
  ei->size = hi - *segbase;
136
0
  if (ei->size > MAX_VDSO_SIZE) 
137
0
  {
138
0
    maps_close (&mi);
139
0
    goto err_exit;
140
0
  }
141
142
0
  a = unw_get_accessors (as);
143
0
  if (! a->access_mem) 
144
0
  {
145
0
    maps_close (&mi);
146
0
    goto err_exit;
147
0
  }
148
149
  /* Try to decide whether it's an ELF image before bringing it all
150
     in.  */
151
0
  if (ei->size <= EI_CLASS || ei->size <= sizeof (magic))
152
0
  {
153
0
    maps_close (&mi);
154
0
    goto err_exit;
155
0
  }
156
157
0
  if (sizeof (magic) >= SELFMAG)
158
0
    {
159
0
      int ret = (*a->access_mem) (as, *segbase, &magic, 0, arg);
160
0
      if (ret < 0)
161
0
      {
162
0
        rc = ret;
163
0
        maps_close (&mi);
164
0
        goto err_exit;
165
0
      }
166
167
0
      if (memcmp (&magic, ELFMAG, SELFMAG) != 0)
168
0
      {
169
0
        maps_close (&mi);
170
0
        goto err_exit;
171
0
      }
172
0
    }
173
174
0
  ei->image = mmap (0, ei->size, PROT_READ | PROT_WRITE,
175
0
           MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
176
0
  if (ei->image == MAP_FAILED)
177
0
    {
178
0
      maps_close (&mi);
179
0
      goto err_exit;
180
0
    }
181
182
0
  if (sizeof (magic) >= SELFMAG)
183
0
    {
184
0
      *(unw_word_t *)ei->image = magic;
185
0
      hi = sizeof (magic);
186
0
    }
187
0
  else
188
0
    hi = 0;
189
190
0
  for (; hi < ei->size; hi += sizeof (unw_word_t))
191
0
    {
192
0
      rc = (*a->access_mem) (as, *segbase + hi, ei->image + hi,
193
0
               0, arg);
194
0
      if (rc < 0)
195
0
   {
196
0
     munmap (ei->image, ei->size);
197
0
     maps_close (&mi);
198
0
     goto err_exit;
199
0
   }
200
0
    }
201
202
0
  if (*segbase == *mapoff
203
0
      && (*path == 0 || strcmp (path, "[vdso]") == 0))
204
0
    *mapoff = 0;
205
206
29.5k
err_exit:
207
208
29.5k
  if (!path)
209
0
    free (full_path);
210
211
29.5k
  maps_close (&mi);
212
29.5k
  return rc;
213
0
}
214
215
#ifndef UNW_REMOTE_ONLY
216
217
void
218
tdep_get_exe_image_path (char *path)
219
0
{
220
0
  strcpy(path, "/proc/self/exe");
221
0
}
222
223
#endif /* !UNW_REMOTE_ONLY */