2010-04-04 Stan Shebs <stan@codesourcery.com>
[deliverable/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
99 data_address = read_memory_typed_address (pointer_address, ptr_type);
100
101 /* Possibly still not initialized such as during an inferior startup. */
102 if (data_address == 0)
103 return -1;
104
105 data_address += offset;
106
107 if (writebuf != NULL)
108 {
109 if (target_write_memory (data_address, writebuf, len) == 0)
110 return len;
111 else
112 return -1;
113 }
114
115 /* Stop if trying to read past the existing AUXV block. The final AT_NULL
116 was already returned before. */
117
118 if (offset >= auxv_pair_size)
119 {
120 if (target_read_memory (data_address - auxv_pair_size, ptr_buf,
121 ptr_size) != 0)
122 return -1;
123
124 if (extract_typed_address (ptr_buf, ptr_type) == AT_NULL)
125 return 0;
126 }
127
128 retval = 0;
129 block = 0x400;
130 gdb_assert (block % auxv_pair_size == 0);
131
132 while (len > 0)
133 {
134 if (block > len)
135 block = len;
136
137 /* Reading sizes smaller than AUXV_PAIR_SIZE is not supported. Tails
138 unaligned to AUXV_PAIR_SIZE will not be read during a call (they
139 should be completed during next read with new/extended buffer). */
140
141 block &= -auxv_pair_size;
142 if (block == 0)
143 return retval;
144
145 if (target_read_memory (data_address, readbuf, block) != 0)
146 {
147 if (block <= auxv_pair_size)
148 return retval;
149
150 block = auxv_pair_size;
151 continue;
152 }
153
154 data_address += block;
155 len -= block;
156
157 /* Check terminal AT_NULL. This function is being called indefinitely
158 being extended its READBUF until it returns EOF (0). */
159
160 while (block >= auxv_pair_size)
161 {
162 retval += auxv_pair_size;
163
164 if (extract_typed_address (readbuf, ptr_type) == AT_NULL)
165 return retval;
166
167 readbuf += auxv_pair_size;
168 block -= auxv_pair_size;
169 }
170 }
171
172 return retval;
173}
174
175/* This function is called like a to_xfer_partial hook, but must be
176 called with TARGET_OBJECT_AUXV. It handles access to AUXV. */
177
178LONGEST
179memory_xfer_auxv (struct target_ops *ops,
180 enum target_object object,
181 const char *annex,
182 gdb_byte *readbuf,
183 const gdb_byte *writebuf,
184 ULONGEST offset,
185 LONGEST len)
186{
187 gdb_assert (object == TARGET_OBJECT_AUXV);
188 gdb_assert (readbuf || writebuf);
189
190 /* ld_so_xfer_auxv is the only function safe for virtual executables being
191 executed by valgrind's memcheck. As using ld_so_xfer_auxv is problematic
192 during inferior startup GDB does call it only for attached processes. */
193
194 if (current_inferior ()->attach_flag != 0)
195 {
196 LONGEST retval;
197
198 retval = ld_so_xfer_auxv (readbuf, writebuf, offset, len);
199 if (retval != -1)
200 return retval;
201 }
202
203 return procfs_xfer_auxv (readbuf, writebuf, offset, len);
204}
205
14ed0a8b
RM
206/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
207 Return 0 if *READPTR is already at the end of the buffer.
208 Return -1 if there is insufficient buffer for a whole entry.
209 Return 1 if an entry was read into *TYPEP and *VALP. */
2c0b251b 210static int
c47ffbe3 211default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
36aa5e41 212 gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
14ed0a8b 213{
ffe5a37e
UW
214 const int sizeof_auxv_field = gdbarch_ptr_bit (target_gdbarch)
215 / TARGET_CHAR_BIT;
e17a4113 216 const enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
36aa5e41 217 gdb_byte *ptr = *readptr;
14ed0a8b
RM
218
219 if (endptr == ptr)
220 return 0;
221
222 if (endptr - ptr < sizeof_auxv_field * 2)
223 return -1;
224
e17a4113 225 *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
14ed0a8b 226 ptr += sizeof_auxv_field;
e17a4113 227 *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
14ed0a8b
RM
228 ptr += sizeof_auxv_field;
229
230 *readptr = ptr;
231 return 1;
232}
233
c47ffbe3
VP
234/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
235 Return 0 if *READPTR is already at the end of the buffer.
236 Return -1 if there is insufficient buffer for a whole entry.
237 Return 1 if an entry was read into *TYPEP and *VALP. */
238int
239target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
240 gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
241{
242 struct target_ops *t;
243 for (t = ops; t != NULL; t = t->beneath)
244 if (t->to_auxv_parse != NULL)
245 return t->to_auxv_parse (t, readptr, endptr, typep, valp);
246
247 return default_auxv_parse (ops, readptr, endptr, typep, valp);
248}
249
14ed0a8b
RM
250/* Extract the auxiliary vector entry with a_type matching MATCH.
251 Return zero if no such entry was found, or -1 if there was
252 an error getting the information. On success, return 1 after
253 storing the entry's value field in *VALP. */
254int
255target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
256{
257 CORE_ADDR type, val;
36aa5e41 258 gdb_byte *data;
13547ab6 259 LONGEST n = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL, &data);
36aa5e41 260 gdb_byte *ptr = data;
14ed0a8b
RM
261 int ents = 0;
262
263 if (n <= 0)
264 return n;
265
266 while (1)
267 switch (target_auxv_parse (ops, &ptr, data + n, &type, &val))
268 {
269 case 1: /* Here's an entry, check it. */
270 if (type == match)
271 {
272 xfree (data);
273 *valp = val;
274 return 1;
275 }
276 break;
277 case 0: /* End of the vector. */
278 xfree (data);
279 return 0;
280 default: /* Bogosity. */
281 xfree (data);
282 return -1;
283 }
284
285 /*NOTREACHED*/
286}
287
288
289/* Print the contents of the target's AUXV on the specified file. */
290int
291fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
292{
293 CORE_ADDR type, val;
36aa5e41 294 gdb_byte *data;
13547ab6
DJ
295 LONGEST len = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL,
296 &data);
36aa5e41 297 gdb_byte *ptr = data;
14ed0a8b
RM
298 int ents = 0;
299
300 if (len <= 0)
301 return len;
302
303 while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
304 {
14ed0a8b
RM
305 const char *name = "???";
306 const char *description = "";
307 enum { dec, hex, str } flavor = hex;
308
309 switch (type)
310 {
311#define TAG(tag, text, kind) \
312 case tag: name = #tag; description = text; flavor = kind; break
edefbb7c
AC
313 TAG (AT_NULL, _("End of vector"), hex);
314 TAG (AT_IGNORE, _("Entry should be ignored"), hex);
315 TAG (AT_EXECFD, _("File descriptor of program"), dec);
316 TAG (AT_PHDR, _("Program headers for program"), hex);
317 TAG (AT_PHENT, _("Size of program header entry"), dec);
318 TAG (AT_PHNUM, _("Number of program headers"), dec);
319 TAG (AT_PAGESZ, _("System page size"), dec);
320 TAG (AT_BASE, _("Base address of interpreter"), hex);
321 TAG (AT_FLAGS, _("Flags"), hex);
322 TAG (AT_ENTRY, _("Entry point of program"), hex);
323 TAG (AT_NOTELF, _("Program is not ELF"), dec);
324 TAG (AT_UID, _("Real user ID"), dec);
325 TAG (AT_EUID, _("Effective user ID"), dec);
326 TAG (AT_GID, _("Real group ID"), dec);
327 TAG (AT_EGID, _("Effective group ID"), dec);
328 TAG (AT_CLKTCK, _("Frequency of times()"), dec);
329 TAG (AT_PLATFORM, _("String identifying platform"), str);
330 TAG (AT_HWCAP, _("Machine-dependent CPU capability hints"), hex);
331 TAG (AT_FPUCW, _("Used FPU control word"), dec);
332 TAG (AT_DCACHEBSIZE, _("Data cache block size"), dec);
333 TAG (AT_ICACHEBSIZE, _("Instruction cache block size"), dec);
334 TAG (AT_UCACHEBSIZE, _("Unified cache block size"), dec);
335 TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec);
759cc328 336 TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str);
ba30a4e9 337 TAG (AT_RANDOM, _("Address of 16 random bytes"), hex);
759cc328
UW
338 TAG (AT_EXECFN, _("File name of executable"), str);
339 TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec);
edefbb7c
AC
340 TAG (AT_SYSINFO, _("Special system info/entry points"), hex);
341 TAG (AT_SYSINFO_EHDR, _("System-supplied DSO's ELF header"), hex);
edefbb7c
AC
342 TAG (AT_SUN_UID, _("Effective user ID"), dec);
343 TAG (AT_SUN_RUID, _("Real user ID"), dec);
344 TAG (AT_SUN_GID, _("Effective group ID"), dec);
345 TAG (AT_SUN_RGID, _("Real group ID"), dec);
346 TAG (AT_SUN_LDELF, _("Dynamic linker's ELF header"), hex);
347 TAG (AT_SUN_LDSHDR, _("Dynamic linker's section headers"), hex);
348 TAG (AT_SUN_LDNAME, _("String giving name of dynamic linker"), str);
349 TAG (AT_SUN_LPAGESZ, _("Large pagesize"), dec);
350 TAG (AT_SUN_PLATFORM, _("Platform name string"), str);
351 TAG (AT_SUN_HWCAP, _("Machine-dependent CPU capability hints"), hex);
352 TAG (AT_SUN_IFLUSH, _("Should flush icache?"), dec);
353 TAG (AT_SUN_CPU, _("CPU name string"), str);
354 TAG (AT_SUN_EMUL_ENTRY, _("COFF entry point address"), hex);
355 TAG (AT_SUN_EMUL_EXECFD, _("COFF executable file descriptor"), dec);
14ed0a8b 356 TAG (AT_SUN_EXECNAME,
edefbb7c
AC
357 _("Canonicalized file name given to execve"), str);
358 TAG (AT_SUN_MMU, _("String for name of MMU module"), str);
359 TAG (AT_SUN_LDDATA, _("Dynamic linker's data segment address"), hex);
77d49ac6
MK
360 TAG (AT_SUN_AUXFLAGS,
361 _("AF_SUN_ flags passed from the kernel"), hex);
14ed0a8b
RM
362 }
363
364 fprintf_filtered (file, "%-4s %-20s %-30s ",
623d3eb1 365 plongest (type), name, description);
14ed0a8b
RM
366 switch (flavor)
367 {
368 case dec:
623d3eb1 369 fprintf_filtered (file, "%s\n", plongest (val));
14ed0a8b
RM
370 break;
371 case hex:
5af949e3 372 fprintf_filtered (file, "%s\n", paddress (target_gdbarch, val));
14ed0a8b
RM
373 break;
374 case str:
79a45b7d
TT
375 {
376 struct value_print_options opts;
377 get_user_print_options (&opts);
378 if (opts.addressprint)
5af949e3 379 fprintf_filtered (file, "%s", paddress (target_gdbarch, val));
6c7a06a3
TT
380 val_print_string (builtin_type (target_gdbarch)->builtin_char,
381 val, -1, file, &opts);
79a45b7d
TT
382 fprintf_filtered (file, "\n");
383 }
14ed0a8b
RM
384 break;
385 }
386 ++ents;
7c6467a4
PP
387 if (type == AT_NULL)
388 break;
14ed0a8b
RM
389 }
390
391 xfree (data);
392
393 return ents;
394}
395
396static void
397info_auxv_command (char *cmd, int from_tty)
398{
14ed0a8b 399 if (! target_has_stack)
edefbb7c 400 error (_("The program has no auxiliary information now."));
14ed0a8b
RM
401 else
402 {
403 int ents = fprint_target_auxv (gdb_stdout, &current_target);
404 if (ents < 0)
edefbb7c 405 error (_("No auxiliary vector found, or failed reading it."));
14ed0a8b 406 else if (ents == 0)
edefbb7c 407 error (_("Auxiliary vector is empty."));
14ed0a8b
RM
408 }
409}
410
411
412extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */
413
414void
415_initialize_auxv (void)
416{
417 add_info ("auxv", info_auxv_command,
edefbb7c
AC
418 _("Display the inferior's auxiliary vector.\n\
419This is information provided by the operating system at program startup."));
14ed0a8b 420}
This page took 0.552447 seconds and 4 git commands to generate.