]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/auxv.c
gdb/
[thirdparty/binutils-gdb.git] / gdb / auxv.c
CommitLineData
14ed0a8b
RM
1/* Auxiliary vector support for GDB, the GNU debugger.
2
4c38e0a4 3 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
0fb0cc75 4 Free Software Foundation, Inc.
14ed0a8b
RM
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
14ed0a8b
RM
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
14ed0a8b
RM
20
21#include "defs.h"
22#include "target.h"
23#include "gdbtypes.h"
24#include "command.h"
25#include "inferior.h"
26#include "valprint.h"
27#include "gdb_assert.h"
9f2982ff 28#include "gdbcore.h"
14ed0a8b
RM
29
30#include "auxv.h"
31#include "elf/common.h"
32
33#include <unistd.h>
34#include <fcntl.h>
35
36
9f2982ff
JK
37/* This function handles access via /proc/PID/auxv, which is a common method
38 for native targets. */
14ed0a8b 39
9f2982ff
JK
40static LONGEST
41procfs_xfer_auxv (gdb_byte *readbuf,
36aa5e41 42 const gdb_byte *writebuf,
14ed0a8b
RM
43 ULONGEST offset,
44 LONGEST len)
45{
46 char *pathname;
47 int fd;
48 LONGEST n;
49
14ed0a8b
RM
50 pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid));
51 fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY);
52 xfree (pathname);
53 if (fd < 0)
54 return -1;
55
56 if (offset != (ULONGEST) 0
57 && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
58 n = -1;
59 else if (readbuf != NULL)
60 n = read (fd, readbuf, len);
61 else
62 n = write (fd, writebuf, len);
63
64 (void) close (fd);
65
66 return n;
67}
68
9f2982ff
JK
69/* This function handles access via ld.so's symbol `_dl_auxv'. */
70
71static LONGEST
72ld_so_xfer_auxv (gdb_byte *readbuf,
73 const gdb_byte *writebuf,
74 ULONGEST offset,
75 LONGEST len)
76{
77 struct minimal_symbol *msym;
78 CORE_ADDR data_address, pointer_address;
79 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
80 size_t ptr_size = TYPE_LENGTH (ptr_type);
81 size_t auxv_pair_size = 2 * ptr_size;
82 gdb_byte *ptr_buf = alloca (ptr_size);
83 LONGEST retval;
84 size_t block;
85
86 msym = lookup_minimal_symbol ("_dl_auxv", NULL, NULL);
87 if (msym == NULL)
88 return -1;
89
90 if (MSYMBOL_SIZE (msym) != ptr_size)
91 return -1;
92
93 /* POINTER_ADDRESS is a location where the `_dl_auxv' variable resides.
94 DATA_ADDRESS is the inferior value present in `_dl_auxv', therefore the
95 real inferior AUXV address. */
96
97 pointer_address = SYMBOL_VALUE_ADDRESS (msym);
98
3cd07d20
JK
99 /* The location of the _dl_auxv symbol may no longer be correct if
100 ld.so runs at a different address than the one present in the file.
101 This is very common case - for unprelinked ld.so or with a PIE executable.
102 PIE executable forces random address even for libraries already being
103 prelinked to some address. PIE executables themselves are never prelinked
104 even on prelinked systems. Prelinking of a PIE executable would block
105 their purpose of randomizing load of everything including the executable.
106
107 If the memory read fails, return -1 to fallback on another mechanism for
108 retrieving the AUXV.
109
110 In most cases of a PIE running under valgrind there is no way to find
111 out the base addresses of any of ld.so, executable or AUXV as everything
112 is randomized and /proc information is not relevant for the virtual
113 executable running under valgrind. We think that we might need a valgrind
114 extension to make it work. This is PR 11440. */
115
116 if (target_read_memory (pointer_address, ptr_buf, ptr_size) != 0)
117 return -1;
118
119 data_address = extract_typed_address (ptr_buf, ptr_type);
9f2982ff
JK
120
121 /* Possibly still not initialized such as during an inferior startup. */
122 if (data_address == 0)
123 return -1;
124
125 data_address += offset;
126
127 if (writebuf != NULL)
128 {
129 if (target_write_memory (data_address, writebuf, len) == 0)
130 return len;
131 else
132 return -1;
133 }
134
135 /* Stop if trying to read past the existing AUXV block. The final AT_NULL
136 was already returned before. */
137
138 if (offset >= auxv_pair_size)
139 {
140 if (target_read_memory (data_address - auxv_pair_size, ptr_buf,
141 ptr_size) != 0)
142 return -1;
143
144 if (extract_typed_address (ptr_buf, ptr_type) == AT_NULL)
145 return 0;
146 }
147
148 retval = 0;
149 block = 0x400;
150 gdb_assert (block % auxv_pair_size == 0);
151
152 while (len > 0)
153 {
154 if (block > len)
155 block = len;
156
157 /* Reading sizes smaller than AUXV_PAIR_SIZE is not supported. Tails
158 unaligned to AUXV_PAIR_SIZE will not be read during a call (they
159 should be completed during next read with new/extended buffer). */
160
161 block &= -auxv_pair_size;
162 if (block == 0)
163 return retval;
164
165 if (target_read_memory (data_address, readbuf, block) != 0)
166 {
167 if (block <= auxv_pair_size)
168 return retval;
169
170 block = auxv_pair_size;
171 continue;
172 }
173
174 data_address += block;
175 len -= block;
176
177 /* Check terminal AT_NULL. This function is being called indefinitely
178 being extended its READBUF until it returns EOF (0). */
179
180 while (block >= auxv_pair_size)
181 {
182 retval += auxv_pair_size;
183
184 if (extract_typed_address (readbuf, ptr_type) == AT_NULL)
185 return retval;
186
187 readbuf += auxv_pair_size;
188 block -= auxv_pair_size;
189 }
190 }
191
192 return retval;
193}
194
195/* This function is called like a to_xfer_partial hook, but must be
196 called with TARGET_OBJECT_AUXV. It handles access to AUXV. */
197
198LONGEST
199memory_xfer_auxv (struct target_ops *ops,
200 enum target_object object,
201 const char *annex,
202 gdb_byte *readbuf,
203 const gdb_byte *writebuf,
204 ULONGEST offset,
205 LONGEST len)
206{
207 gdb_assert (object == TARGET_OBJECT_AUXV);
208 gdb_assert (readbuf || writebuf);
209
210 /* ld_so_xfer_auxv is the only function safe for virtual executables being
211 executed by valgrind's memcheck. As using ld_so_xfer_auxv is problematic
212 during inferior startup GDB does call it only for attached processes. */
213
214 if (current_inferior ()->attach_flag != 0)
215 {
216 LONGEST retval;
217
218 retval = ld_so_xfer_auxv (readbuf, writebuf, offset, len);
219 if (retval != -1)
220 return retval;
221 }
222
223 return procfs_xfer_auxv (readbuf, writebuf, offset, len);
224}
225
14ed0a8b
RM
226/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
227 Return 0 if *READPTR is already at the end of the buffer.
228 Return -1 if there is insufficient buffer for a whole entry.
229 Return 1 if an entry was read into *TYPEP and *VALP. */
2c0b251b 230static int
c47ffbe3 231default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
36aa5e41 232 gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
14ed0a8b 233{
ffe5a37e
UW
234 const int sizeof_auxv_field = gdbarch_ptr_bit (target_gdbarch)
235 / TARGET_CHAR_BIT;
e17a4113 236 const enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
36aa5e41 237 gdb_byte *ptr = *readptr;
14ed0a8b
RM
238
239 if (endptr == ptr)
240 return 0;
241
242 if (endptr - ptr < sizeof_auxv_field * 2)
243 return -1;
244
e17a4113 245 *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
14ed0a8b 246 ptr += sizeof_auxv_field;
e17a4113 247 *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
14ed0a8b
RM
248 ptr += sizeof_auxv_field;
249
250 *readptr = ptr;
251 return 1;
252}
253
c47ffbe3
VP
254/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
255 Return 0 if *READPTR is already at the end of the buffer.
256 Return -1 if there is insufficient buffer for a whole entry.
257 Return 1 if an entry was read into *TYPEP and *VALP. */
258int
259target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
260 gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
261{
262 struct target_ops *t;
5b4ee69b 263
c47ffbe3
VP
264 for (t = ops; t != NULL; t = t->beneath)
265 if (t->to_auxv_parse != NULL)
266 return t->to_auxv_parse (t, readptr, endptr, typep, valp);
267
268 return default_auxv_parse (ops, readptr, endptr, typep, valp);
269}
270
14ed0a8b
RM
271/* Extract the auxiliary vector entry with a_type matching MATCH.
272 Return zero if no such entry was found, or -1 if there was
273 an error getting the information. On success, return 1 after
274 storing the entry's value field in *VALP. */
275int
276target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
277{
278 CORE_ADDR type, val;
36aa5e41 279 gdb_byte *data;
13547ab6 280 LONGEST n = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL, &data);
36aa5e41 281 gdb_byte *ptr = data;
14ed0a8b
RM
282
283 if (n <= 0)
284 return n;
285
286 while (1)
287 switch (target_auxv_parse (ops, &ptr, data + n, &type, &val))
288 {
289 case 1: /* Here's an entry, check it. */
290 if (type == match)
291 {
292 xfree (data);
293 *valp = val;
294 return 1;
295 }
296 break;
297 case 0: /* End of the vector. */
298 xfree (data);
299 return 0;
300 default: /* Bogosity. */
301 xfree (data);
302 return -1;
303 }
304
305 /*NOTREACHED*/
306}
307
308
309/* Print the contents of the target's AUXV on the specified file. */
310int
311fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
312{
313 CORE_ADDR type, val;
36aa5e41 314 gdb_byte *data;
13547ab6
DJ
315 LONGEST len = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL,
316 &data);
36aa5e41 317 gdb_byte *ptr = data;
14ed0a8b
RM
318 int ents = 0;
319
320 if (len <= 0)
321 return len;
322
323 while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
324 {
14ed0a8b
RM
325 const char *name = "???";
326 const char *description = "";
327 enum { dec, hex, str } flavor = hex;
328
329 switch (type)
330 {
331#define TAG(tag, text, kind) \
332 case tag: name = #tag; description = text; flavor = kind; break
edefbb7c
AC
333 TAG (AT_NULL, _("End of vector"), hex);
334 TAG (AT_IGNORE, _("Entry should be ignored"), hex);
335 TAG (AT_EXECFD, _("File descriptor of program"), dec);
336 TAG (AT_PHDR, _("Program headers for program"), hex);
337 TAG (AT_PHENT, _("Size of program header entry"), dec);
338 TAG (AT_PHNUM, _("Number of program headers"), dec);
339 TAG (AT_PAGESZ, _("System page size"), dec);
340 TAG (AT_BASE, _("Base address of interpreter"), hex);
341 TAG (AT_FLAGS, _("Flags"), hex);
342 TAG (AT_ENTRY, _("Entry point of program"), hex);
343 TAG (AT_NOTELF, _("Program is not ELF"), dec);
344 TAG (AT_UID, _("Real user ID"), dec);
345 TAG (AT_EUID, _("Effective user ID"), dec);
346 TAG (AT_GID, _("Real group ID"), dec);
347 TAG (AT_EGID, _("Effective group ID"), dec);
348 TAG (AT_CLKTCK, _("Frequency of times()"), dec);
349 TAG (AT_PLATFORM, _("String identifying platform"), str);
350 TAG (AT_HWCAP, _("Machine-dependent CPU capability hints"), hex);
351 TAG (AT_FPUCW, _("Used FPU control word"), dec);
352 TAG (AT_DCACHEBSIZE, _("Data cache block size"), dec);
353 TAG (AT_ICACHEBSIZE, _("Instruction cache block size"), dec);
354 TAG (AT_UCACHEBSIZE, _("Unified cache block size"), dec);
355 TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec);
759cc328 356 TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str);
ba30a4e9 357 TAG (AT_RANDOM, _("Address of 16 random bytes"), hex);
759cc328
UW
358 TAG (AT_EXECFN, _("File name of executable"), str);
359 TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec);
edefbb7c
AC
360 TAG (AT_SYSINFO, _("Special system info/entry points"), hex);
361 TAG (AT_SYSINFO_EHDR, _("System-supplied DSO's ELF header"), hex);
edefbb7c
AC
362 TAG (AT_SUN_UID, _("Effective user ID"), dec);
363 TAG (AT_SUN_RUID, _("Real user ID"), dec);
364 TAG (AT_SUN_GID, _("Effective group ID"), dec);
365 TAG (AT_SUN_RGID, _("Real group ID"), dec);
366 TAG (AT_SUN_LDELF, _("Dynamic linker's ELF header"), hex);
367 TAG (AT_SUN_LDSHDR, _("Dynamic linker's section headers"), hex);
368 TAG (AT_SUN_LDNAME, _("String giving name of dynamic linker"), str);
369 TAG (AT_SUN_LPAGESZ, _("Large pagesize"), dec);
370 TAG (AT_SUN_PLATFORM, _("Platform name string"), str);
371 TAG (AT_SUN_HWCAP, _("Machine-dependent CPU capability hints"), hex);
372 TAG (AT_SUN_IFLUSH, _("Should flush icache?"), dec);
373 TAG (AT_SUN_CPU, _("CPU name string"), str);
374 TAG (AT_SUN_EMUL_ENTRY, _("COFF entry point address"), hex);
375 TAG (AT_SUN_EMUL_EXECFD, _("COFF executable file descriptor"), dec);
14ed0a8b 376 TAG (AT_SUN_EXECNAME,
edefbb7c
AC
377 _("Canonicalized file name given to execve"), str);
378 TAG (AT_SUN_MMU, _("String for name of MMU module"), str);
379 TAG (AT_SUN_LDDATA, _("Dynamic linker's data segment address"), hex);
77d49ac6
MK
380 TAG (AT_SUN_AUXFLAGS,
381 _("AF_SUN_ flags passed from the kernel"), hex);
14ed0a8b
RM
382 }
383
384 fprintf_filtered (file, "%-4s %-20s %-30s ",
623d3eb1 385 plongest (type), name, description);
14ed0a8b
RM
386 switch (flavor)
387 {
388 case dec:
623d3eb1 389 fprintf_filtered (file, "%s\n", plongest (val));
14ed0a8b
RM
390 break;
391 case hex:
5af949e3 392 fprintf_filtered (file, "%s\n", paddress (target_gdbarch, val));
14ed0a8b
RM
393 break;
394 case str:
79a45b7d
TT
395 {
396 struct value_print_options opts;
5b4ee69b 397
79a45b7d
TT
398 get_user_print_options (&opts);
399 if (opts.addressprint)
5af949e3 400 fprintf_filtered (file, "%s", paddress (target_gdbarch, val));
6c7a06a3
TT
401 val_print_string (builtin_type (target_gdbarch)->builtin_char,
402 val, -1, file, &opts);
79a45b7d
TT
403 fprintf_filtered (file, "\n");
404 }
14ed0a8b
RM
405 break;
406 }
407 ++ents;
7c6467a4
PP
408 if (type == AT_NULL)
409 break;
14ed0a8b
RM
410 }
411
412 xfree (data);
413
414 return ents;
415}
416
417static void
418info_auxv_command (char *cmd, int from_tty)
419{
14ed0a8b 420 if (! target_has_stack)
edefbb7c 421 error (_("The program has no auxiliary information now."));
14ed0a8b
RM
422 else
423 {
424 int ents = fprint_target_auxv (gdb_stdout, &current_target);
5b4ee69b 425
14ed0a8b 426 if (ents < 0)
edefbb7c 427 error (_("No auxiliary vector found, or failed reading it."));
14ed0a8b 428 else if (ents == 0)
edefbb7c 429 error (_("Auxiliary vector is empty."));
14ed0a8b
RM
430 }
431}
432
433
434extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */
435
436void
437_initialize_auxv (void)
438{
439 add_info ("auxv", info_auxv_command,
edefbb7c
AC
440 _("Display the inferior's auxiliary vector.\n\
441This is information provided by the operating system at program startup."));
14ed0a8b 442}