xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/auxv.c (revision 32d1c65c71fbdb65a012e8392a62a757dd6853e9)
1 /* Auxiliary vector support for GDB, the GNU debugger.
2 
3    Copyright (C) 2004-2023 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include "defs.h"
21 #include "target.h"
22 #include "gdbtypes.h"
23 #include "command.h"
24 #include "inferior.h"
25 #include "valprint.h"
26 #include "gdbcore.h"
27 #include "observable.h"
28 #include "gdbsupport/filestuff.h"
29 #include "objfiles.h"
30 
31 #include "auxv.h"
32 #include "elf/common.h"
33 
34 #include <unistd.h>
35 #include <fcntl.h>
36 
37 
38 /* Implement the to_xfer_partial target_ops method.  This function
39    handles access via /proc/PID/auxv, which is a common method for
40    native targets.  */
41 
42 static enum target_xfer_status
43 procfs_xfer_auxv (gdb_byte *readbuf,
44 		  const gdb_byte *writebuf,
45 		  ULONGEST offset,
46 		  ULONGEST len,
47 		  ULONGEST *xfered_len)
48 {
49   ssize_t l;
50 
51   std::string pathname = string_printf ("/proc/%d/auxv", inferior_ptid.pid ());
52   scoped_fd fd
53     = gdb_open_cloexec (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY, 0);
54   if (fd.get () < 0)
55     return TARGET_XFER_E_IO;
56 
57   if (offset != (ULONGEST) 0
58       && lseek (fd.get (), (off_t) offset, SEEK_SET) != (off_t) offset)
59     l = -1;
60   else if (readbuf != NULL)
61     l = read (fd.get (), readbuf, (size_t) len);
62   else
63     l = write (fd.get (), writebuf, (size_t) len);
64 
65   if (l < 0)
66     return TARGET_XFER_E_IO;
67   else if (l == 0)
68     return TARGET_XFER_EOF;
69   else
70     {
71       *xfered_len = (ULONGEST) l;
72       return TARGET_XFER_OK;
73     }
74 }
75 
76 /* This function handles access via ld.so's symbol `_dl_auxv'.  */
77 
78 static enum target_xfer_status
79 ld_so_xfer_auxv (gdb_byte *readbuf,
80 		 const gdb_byte *writebuf,
81 		 ULONGEST offset,
82 		 ULONGEST len, ULONGEST *xfered_len)
83 {
84   struct bound_minimal_symbol msym;
85   CORE_ADDR data_address, pointer_address;
86   struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
87   size_t ptr_size = ptr_type->length ();
88   size_t auxv_pair_size = 2 * ptr_size;
89   gdb_byte *ptr_buf = (gdb_byte *) alloca (ptr_size);
90   LONGEST retval;
91   size_t block;
92 
93   msym = lookup_minimal_symbol ("_dl_auxv", NULL, NULL);
94   if (msym.minsym == NULL)
95     return TARGET_XFER_E_IO;
96 
97   if (msym.minsym->size () != ptr_size)
98     return TARGET_XFER_E_IO;
99 
100   /* POINTER_ADDRESS is a location where the `_dl_auxv' variable
101      resides.  DATA_ADDRESS is the inferior value present in
102      `_dl_auxv', therefore the real inferior AUXV address.  */
103 
104   pointer_address = msym.value_address ();
105 
106   /* The location of the _dl_auxv symbol may no longer be correct if
107      ld.so runs at a different address than the one present in the
108      file.  This is very common case - for unprelinked ld.so or with a
109      PIE executable.  PIE executable forces random address even for
110      libraries already being prelinked to some address.  PIE
111      executables themselves are never prelinked even on prelinked
112      systems.  Prelinking of a PIE executable would block their
113      purpose of randomizing load of everything including the
114      executable.
115 
116      If the memory read fails, return -1 to fallback on another
117      mechanism for retrieving the AUXV.
118 
119      In most cases of a PIE running under valgrind there is no way to
120      find out the base addresses of any of ld.so, executable or AUXV
121      as everything is randomized and /proc information is not relevant
122      for the virtual executable running under valgrind.  We think that
123      we might need a valgrind extension to make it work.  This is PR
124      11440.  */
125 
126   if (target_read_memory (pointer_address, ptr_buf, ptr_size) != 0)
127     return TARGET_XFER_E_IO;
128 
129   data_address = extract_typed_address (ptr_buf, ptr_type);
130 
131   /* Possibly still not initialized such as during an inferior
132      startup.  */
133   if (data_address == 0)
134     return TARGET_XFER_E_IO;
135 
136   data_address += offset;
137 
138   if (writebuf != NULL)
139     {
140       if (target_write_memory (data_address, writebuf, len) == 0)
141 	{
142 	  *xfered_len = (ULONGEST) len;
143 	  return TARGET_XFER_OK;
144 	}
145       else
146 	return TARGET_XFER_E_IO;
147     }
148 
149   /* Stop if trying to read past the existing AUXV block.  The final
150      AT_NULL was already returned before.  */
151 
152   if (offset >= auxv_pair_size)
153     {
154       if (target_read_memory (data_address - auxv_pair_size, ptr_buf,
155 			      ptr_size) != 0)
156 	return TARGET_XFER_E_IO;
157 
158       if (extract_typed_address (ptr_buf, ptr_type) == AT_NULL)
159 	return TARGET_XFER_EOF;
160     }
161 
162   retval = 0;
163   block = 0x400;
164   gdb_assert (block % auxv_pair_size == 0);
165 
166   while (len > 0)
167     {
168       if (block > len)
169 	block = len;
170 
171       /* Reading sizes smaller than AUXV_PAIR_SIZE is not supported.
172 	 Tails unaligned to AUXV_PAIR_SIZE will not be read during a
173 	 call (they should be completed during next read with
174 	 new/extended buffer).  */
175 
176       block &= -auxv_pair_size;
177       if (block == 0)
178 	break;
179 
180       if (target_read_memory (data_address, readbuf, block) != 0)
181 	{
182 	  if (block <= auxv_pair_size)
183 	    break;
184 
185 	  block = auxv_pair_size;
186 	  continue;
187 	}
188 
189       data_address += block;
190       len -= block;
191 
192       /* Check terminal AT_NULL.  This function is being called
193 	 indefinitely being extended its READBUF until it returns EOF
194 	 (0).  */
195 
196       while (block >= auxv_pair_size)
197 	{
198 	  retval += auxv_pair_size;
199 
200 	  if (extract_typed_address (readbuf, ptr_type) == AT_NULL)
201 	    {
202 	      *xfered_len = (ULONGEST) retval;
203 	      return TARGET_XFER_OK;
204 	    }
205 
206 	  readbuf += auxv_pair_size;
207 	  block -= auxv_pair_size;
208 	}
209     }
210 
211   *xfered_len = (ULONGEST) retval;
212   return TARGET_XFER_OK;
213 }
214 
215 /* Implement the to_xfer_partial target_ops method for
216    TARGET_OBJECT_AUXV.  It handles access to AUXV.  */
217 
218 enum target_xfer_status
219 memory_xfer_auxv (struct target_ops *ops,
220 		  enum target_object object,
221 		  const char *annex,
222 		  gdb_byte *readbuf,
223 		  const gdb_byte *writebuf,
224 		  ULONGEST offset,
225 		  ULONGEST len, ULONGEST *xfered_len)
226 {
227   gdb_assert (object == TARGET_OBJECT_AUXV);
228   gdb_assert (readbuf || writebuf);
229 
230    /* ld_so_xfer_auxv is the only function safe for virtual
231       executables being executed by valgrind's memcheck.  Using
232       ld_so_xfer_auxv during inferior startup is problematic, because
233       ld.so symbol tables have not yet been relocated.  So GDB uses
234       this function only when attaching to a process.
235       */
236 
237   if (current_inferior ()->attach_flag)
238     {
239       enum target_xfer_status ret;
240 
241       ret = ld_so_xfer_auxv (readbuf, writebuf, offset, len, xfered_len);
242       if (ret != TARGET_XFER_E_IO)
243 	return ret;
244     }
245 
246   return procfs_xfer_auxv (readbuf, writebuf, offset, len, xfered_len);
247 }
248 
249 /* This function compared to other auxv_parse functions: it takes the size of
250    the auxv type field as a parameter.  */
251 
252 static int
253 generic_auxv_parse (struct gdbarch *gdbarch, const gdb_byte **readptr,
254 		    const gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp,
255 		    int sizeof_auxv_type)
256 {
257   struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
258   const int sizeof_auxv_val = ptr_type->length ();
259   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
260   const gdb_byte *ptr = *readptr;
261 
262   if (endptr == ptr)
263     return 0;
264 
265   if (endptr - ptr < 2 * sizeof_auxv_val)
266     return -1;
267 
268   *typep = extract_unsigned_integer (ptr, sizeof_auxv_type, byte_order);
269   /* Even if the auxv type takes less space than an auxv value, there is
270      padding after the type such that the value is aligned on a multiple of
271      its size (and this is why we advance by `sizeof_auxv_val` and not
272      `sizeof_auxv_type`).  */
273   ptr += sizeof_auxv_val;
274   *valp = extract_unsigned_integer (ptr, sizeof_auxv_val, byte_order);
275   ptr += sizeof_auxv_val;
276 
277   *readptr = ptr;
278   return 1;
279 }
280 
281 /* See auxv.h.  */
282 
283 int
284 default_auxv_parse (struct target_ops *ops, const gdb_byte **readptr,
285 		    const gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
286 {
287   struct gdbarch *gdbarch = target_gdbarch ();
288   struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
289   const int sizeof_auxv_type = ptr_type->length ();
290 
291   return generic_auxv_parse (gdbarch, readptr, endptr, typep, valp,
292 			     sizeof_auxv_type);
293 }
294 
295 /* See auxv.h.  */
296 
297 int
298 svr4_auxv_parse (struct gdbarch *gdbarch, const gdb_byte **readptr,
299 		 const gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
300 {
301   struct type *int_type = builtin_type (gdbarch)->builtin_int;
302   const int sizeof_auxv_type = int_type->length ();
303 
304   return generic_auxv_parse (gdbarch, readptr, endptr, typep, valp,
305 			     sizeof_auxv_type);
306 }
307 
308 /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
309 
310    Use the auxv_parse method from GDBARCH, if defined, else use the auxv_parse
311    method of OPS.
312 
313    Return 0 if *READPTR is already at the end of the buffer.
314    Return -1 if there is insufficient buffer for a whole entry.
315    Return 1 if an entry was read into *TYPEP and *VALP.  */
316 
317 static int
318 parse_auxv (target_ops *ops, gdbarch *gdbarch, const gdb_byte **readptr,
319 	    const gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
320 {
321   if (gdbarch_auxv_parse_p (gdbarch))
322     return gdbarch_auxv_parse (gdbarch, readptr, endptr, typep, valp);
323 
324   return ops->auxv_parse (readptr, endptr, typep, valp);
325 }
326 
327 
328 /*  Auxiliary Vector information structure.  This is used by GDB
329     for caching purposes for each inferior.  This helps reduce the
330     overhead of transfering data from a remote target to the local host.  */
331 struct auxv_info
332 {
333   gdb::optional<gdb::byte_vector> data;
334 };
335 
336 /* Per-inferior data key for auxv.  */
337 static const registry<inferior>::key<auxv_info> auxv_inferior_data;
338 
339 /* Invalidate INF's auxv cache.  */
340 
341 static void
342 invalidate_auxv_cache_inf (struct inferior *inf)
343 {
344   auxv_inferior_data.clear (inf);
345 }
346 
347 /* Invalidate current inferior's auxv cache.  */
348 
349 static void
350 invalidate_auxv_cache (void)
351 {
352   invalidate_auxv_cache_inf (current_inferior ());
353 }
354 
355 /* See auxv.h.  */
356 
357 gdb::optional<gdb::byte_vector>
358 target_read_auxv ()
359 {
360   inferior *inf = current_inferior ();
361   auxv_info *info = auxv_inferior_data.get (inf);
362 
363   if (info == nullptr)
364     {
365       info = auxv_inferior_data.emplace (inf);
366       info->data = target_read_auxv_raw (inf->top_target ());
367     }
368 
369   return info->data;
370 }
371 
372 /* See auxv.h.  */
373 
374 gdb::optional<gdb::byte_vector>
375 target_read_auxv_raw (target_ops *ops)
376 {
377   return target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL);
378 }
379 
380 /* See auxv.h.  */
381 
382 int
383 target_auxv_search (const gdb::byte_vector &auxv, target_ops *ops,
384 		    gdbarch *gdbarch, CORE_ADDR match, CORE_ADDR *valp)
385 {
386   CORE_ADDR type, val;
387   const gdb_byte *data = auxv.data ();
388   const gdb_byte *ptr = data;
389   size_t len = auxv.size ();
390 
391   while (1)
392     switch (parse_auxv (ops, gdbarch, &ptr, data + len, &type, &val))
393       {
394       case 1:			/* Here's an entry, check it.  */
395 	if (type == match)
396 	  {
397 	    *valp = val;
398 	    return 1;
399 	  }
400 	break;
401       case 0:			/* End of the vector.  */
402 	return 0;
403       default:			/* Bogosity.  */
404 	return -1;
405       }
406 }
407 
408 /* See auxv.h.  */
409 
410 int
411 target_auxv_search (CORE_ADDR match, CORE_ADDR *valp)
412 {
413   gdb::optional<gdb::byte_vector> auxv = target_read_auxv ();
414 
415   if (!auxv.has_value ())
416     return -1;
417 
418   return target_auxv_search (*auxv, current_inferior ()->top_target (),
419 			     current_inferior ()->gdbarch, match, valp);
420 }
421 
422 /* Print the description of a single AUXV entry on the specified file.  */
423 
424 void
425 fprint_auxv_entry (struct ui_file *file, const char *name,
426 		   const char *description, enum auxv_format format,
427 		   CORE_ADDR type, CORE_ADDR val)
428 {
429   gdb_printf (file, ("%-4s %-20s %-30s "),
430 	      plongest (type), name, description);
431   switch (format)
432     {
433     case AUXV_FORMAT_DEC:
434       gdb_printf (file, ("%s\n"), plongest (val));
435       break;
436     case AUXV_FORMAT_HEX:
437       gdb_printf (file, ("%s\n"), paddress (target_gdbarch (), val));
438       break;
439     case AUXV_FORMAT_STR:
440       {
441 	struct value_print_options opts;
442 
443 	get_user_print_options (&opts);
444 	if (opts.addressprint)
445 	  gdb_printf (file, ("%s "), paddress (target_gdbarch (), val));
446 	val_print_string (builtin_type (target_gdbarch ())->builtin_char,
447 			  NULL, val, -1, file, &opts);
448 	gdb_printf (file, ("\n"));
449       }
450       break;
451     }
452 }
453 
454 /* The default implementation of gdbarch_print_auxv_entry.  */
455 
456 void
457 default_print_auxv_entry (struct gdbarch *gdbarch, struct ui_file *file,
458 			  CORE_ADDR type, CORE_ADDR val)
459 {
460   const char *name = "???";
461   const char *description = "";
462   enum auxv_format format = AUXV_FORMAT_HEX;
463 
464   switch (type)
465     {
466 #define TAG(tag, text, kind) \
467       case tag: name = #tag; description = text; format = kind; break
468       TAG (AT_NULL, _("End of vector"), AUXV_FORMAT_HEX);
469       TAG (AT_IGNORE, _("Entry should be ignored"), AUXV_FORMAT_HEX);
470       TAG (AT_EXECFD, _("File descriptor of program"), AUXV_FORMAT_DEC);
471       TAG (AT_PHDR, _("Program headers for program"), AUXV_FORMAT_HEX);
472       TAG (AT_PHENT, _("Size of program header entry"), AUXV_FORMAT_DEC);
473       TAG (AT_PHNUM, _("Number of program headers"), AUXV_FORMAT_DEC);
474       TAG (AT_PAGESZ, _("System page size"), AUXV_FORMAT_DEC);
475       TAG (AT_BASE, _("Base address of interpreter"), AUXV_FORMAT_HEX);
476       TAG (AT_FLAGS, _("Flags"), AUXV_FORMAT_HEX);
477       TAG (AT_ENTRY, _("Entry point of program"), AUXV_FORMAT_HEX);
478       TAG (AT_NOTELF, _("Program is not ELF"), AUXV_FORMAT_DEC);
479       TAG (AT_UID, _("Real user ID"), AUXV_FORMAT_DEC);
480       TAG (AT_EUID, _("Effective user ID"), AUXV_FORMAT_DEC);
481       TAG (AT_GID, _("Real group ID"), AUXV_FORMAT_DEC);
482       TAG (AT_EGID, _("Effective group ID"), AUXV_FORMAT_DEC);
483       TAG (AT_CLKTCK, _("Frequency of times()"), AUXV_FORMAT_DEC);
484       TAG (AT_PLATFORM, _("String identifying platform"), AUXV_FORMAT_STR);
485       TAG (AT_HWCAP, _("Machine-dependent CPU capability hints"),
486 	   AUXV_FORMAT_HEX);
487       TAG (AT_FPUCW, _("Used FPU control word"), AUXV_FORMAT_DEC);
488       TAG (AT_DCACHEBSIZE, _("Data cache block size"), AUXV_FORMAT_DEC);
489       TAG (AT_ICACHEBSIZE, _("Instruction cache block size"), AUXV_FORMAT_DEC);
490       TAG (AT_UCACHEBSIZE, _("Unified cache block size"), AUXV_FORMAT_DEC);
491       TAG (AT_IGNOREPPC, _("Entry should be ignored"), AUXV_FORMAT_DEC);
492       TAG (AT_BASE_PLATFORM, _("String identifying base platform"),
493 	   AUXV_FORMAT_STR);
494       TAG (AT_RANDOM, _("Address of 16 random bytes"), AUXV_FORMAT_HEX);
495       TAG (AT_HWCAP2, _("Extension of AT_HWCAP"), AUXV_FORMAT_HEX);
496       TAG (AT_EXECFN, _("File name of executable"), AUXV_FORMAT_STR);
497       TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), AUXV_FORMAT_DEC);
498       TAG (AT_SYSINFO, _("Special system info/entry points"), AUXV_FORMAT_HEX);
499       TAG (AT_SYSINFO_EHDR, _("System-supplied DSO's ELF header"),
500 	   AUXV_FORMAT_HEX);
501       TAG (AT_L1I_CACHESHAPE, _("L1 Instruction cache information"),
502 	   AUXV_FORMAT_HEX);
503       TAG (AT_L1I_CACHESIZE, _("L1 Instruction cache size"), AUXV_FORMAT_HEX);
504       TAG (AT_L1I_CACHEGEOMETRY, _("L1 Instruction cache geometry"),
505 	   AUXV_FORMAT_HEX);
506       TAG (AT_L1D_CACHESHAPE, _("L1 Data cache information"), AUXV_FORMAT_HEX);
507       TAG (AT_L1D_CACHESIZE, _("L1 Data cache size"), AUXV_FORMAT_HEX);
508       TAG (AT_L1D_CACHEGEOMETRY, _("L1 Data cache geometry"),
509 	   AUXV_FORMAT_HEX);
510       TAG (AT_L2_CACHESHAPE, _("L2 cache information"), AUXV_FORMAT_HEX);
511       TAG (AT_L2_CACHESIZE, _("L2 cache size"), AUXV_FORMAT_HEX);
512       TAG (AT_L2_CACHEGEOMETRY, _("L2 cache geometry"), AUXV_FORMAT_HEX);
513       TAG (AT_L3_CACHESHAPE, _("L3 cache information"), AUXV_FORMAT_HEX);
514       TAG (AT_L3_CACHESIZE, _("L3 cache size"), AUXV_FORMAT_HEX);
515       TAG (AT_L3_CACHEGEOMETRY, _("L3 cache geometry"), AUXV_FORMAT_HEX);
516       TAG (AT_MINSIGSTKSZ, _("Minimum stack size for signal delivery"),
517 	   AUXV_FORMAT_HEX);
518       TAG (AT_SUN_UID, _("Effective user ID"), AUXV_FORMAT_DEC);
519       TAG (AT_SUN_RUID, _("Real user ID"), AUXV_FORMAT_DEC);
520       TAG (AT_SUN_GID, _("Effective group ID"), AUXV_FORMAT_DEC);
521       TAG (AT_SUN_RGID, _("Real group ID"), AUXV_FORMAT_DEC);
522       TAG (AT_SUN_LDELF, _("Dynamic linker's ELF header"), AUXV_FORMAT_HEX);
523       TAG (AT_SUN_LDSHDR, _("Dynamic linker's section headers"),
524 	   AUXV_FORMAT_HEX);
525       TAG (AT_SUN_LDNAME, _("String giving name of dynamic linker"),
526 	   AUXV_FORMAT_STR);
527       TAG (AT_SUN_LPAGESZ, _("Large pagesize"), AUXV_FORMAT_DEC);
528       TAG (AT_SUN_PLATFORM, _("Platform name string"), AUXV_FORMAT_STR);
529       TAG (AT_SUN_CAP_HW1, _("Machine-dependent CPU capability hints"),
530 	   AUXV_FORMAT_HEX);
531       TAG (AT_SUN_IFLUSH, _("Should flush icache?"), AUXV_FORMAT_DEC);
532       TAG (AT_SUN_CPU, _("CPU name string"), AUXV_FORMAT_STR);
533       TAG (AT_SUN_EMUL_ENTRY, _("COFF entry point address"), AUXV_FORMAT_HEX);
534       TAG (AT_SUN_EMUL_EXECFD, _("COFF executable file descriptor"),
535 	   AUXV_FORMAT_DEC);
536       TAG (AT_SUN_EXECNAME,
537 	   _("Canonicalized file name given to execve"), AUXV_FORMAT_STR);
538       TAG (AT_SUN_MMU, _("String for name of MMU module"), AUXV_FORMAT_STR);
539       TAG (AT_SUN_LDDATA, _("Dynamic linker's data segment address"),
540 	   AUXV_FORMAT_HEX);
541       TAG (AT_SUN_AUXFLAGS,
542 	   _("AF_SUN_ flags passed from the kernel"), AUXV_FORMAT_HEX);
543       TAG (AT_SUN_EMULATOR, _("Name of emulation binary for runtime linker"),
544 	   AUXV_FORMAT_STR);
545       TAG (AT_SUN_BRANDNAME, _("Name of brand library"), AUXV_FORMAT_STR);
546       TAG (AT_SUN_BRAND_AUX1, _("Aux vector for brand modules 1"),
547 	   AUXV_FORMAT_HEX);
548       TAG (AT_SUN_BRAND_AUX2, _("Aux vector for brand modules 2"),
549 	   AUXV_FORMAT_HEX);
550       TAG (AT_SUN_BRAND_AUX3, _("Aux vector for brand modules 3"),
551 	   AUXV_FORMAT_HEX);
552       TAG (AT_SUN_CAP_HW2, _("Machine-dependent CPU capability hints 2"),
553 	   AUXV_FORMAT_HEX);
554     }
555 
556   fprint_auxv_entry (file, name, description, format, type, val);
557 }
558 
559 /* Print the contents of the target's AUXV on the specified file.  */
560 
561 static int
562 fprint_target_auxv (struct ui_file *file)
563 {
564   struct gdbarch *gdbarch = target_gdbarch ();
565   CORE_ADDR type, val;
566   int ents = 0;
567   gdb::optional<gdb::byte_vector> auxv = target_read_auxv ();
568 
569   if (!auxv.has_value ())
570     return -1;
571 
572   const gdb_byte *data = auxv->data ();
573   const gdb_byte *ptr = data;
574   size_t len = auxv->size ();
575 
576   while (parse_auxv (current_inferior ()->top_target (),
577 		     current_inferior ()->gdbarch,
578 		     &ptr, data + len, &type, &val) > 0)
579     {
580       gdbarch_print_auxv_entry (gdbarch, file, type, val);
581       ++ents;
582       if (type == AT_NULL)
583 	break;
584     }
585 
586   return ents;
587 }
588 
589 static void
590 info_auxv_command (const char *cmd, int from_tty)
591 {
592   if (! target_has_stack ())
593     error (_("The program has no auxiliary information now."));
594   else
595     {
596       int ents = fprint_target_auxv (gdb_stdout);
597 
598       if (ents < 0)
599 	error (_("No auxiliary vector found, or failed reading it."));
600       else if (ents == 0)
601 	error (_("Auxiliary vector is empty."));
602     }
603 }
604 
605 void _initialize_auxv ();
606 void
607 _initialize_auxv ()
608 {
609   add_info ("auxv", info_auxv_command,
610 	    _("Display the inferior's auxiliary vector.\n\
611 This is information provided by the operating system at program startup."));
612 
613   /* Observers used to invalidate the auxv cache when needed.  */
614   gdb::observers::inferior_exit.attach (invalidate_auxv_cache_inf, "auxv");
615   gdb::observers::inferior_appeared.attach (invalidate_auxv_cache_inf, "auxv");
616   gdb::observers::executable_changed.attach (invalidate_auxv_cache, "auxv");
617 }
618