xref: /dflybsd-src/contrib/gdb-7/gdb/auxv.c (revision cf7f2e2d389e8012d562650bd94d7e433f449d6e)
15796c8dcSSimon Schubert /* Auxiliary vector support for GDB, the GNU debugger.
25796c8dcSSimon Schubert 
3*cf7f2e2dSJohn Marino    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
45796c8dcSSimon Schubert    Free Software Foundation, Inc.
55796c8dcSSimon Schubert 
65796c8dcSSimon Schubert    This file is part of GDB.
75796c8dcSSimon Schubert 
85796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
95796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
105796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
115796c8dcSSimon Schubert    (at your option) any later version.
125796c8dcSSimon Schubert 
135796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
145796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
155796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
165796c8dcSSimon Schubert    GNU General Public License for more details.
175796c8dcSSimon Schubert 
185796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
195796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
205796c8dcSSimon Schubert 
215796c8dcSSimon Schubert #include "defs.h"
225796c8dcSSimon Schubert #include "target.h"
235796c8dcSSimon Schubert #include "gdbtypes.h"
245796c8dcSSimon Schubert #include "command.h"
255796c8dcSSimon Schubert #include "inferior.h"
265796c8dcSSimon Schubert #include "valprint.h"
275796c8dcSSimon Schubert #include "gdb_assert.h"
28*cf7f2e2dSJohn Marino #include "gdbcore.h"
295796c8dcSSimon Schubert 
305796c8dcSSimon Schubert #include "auxv.h"
315796c8dcSSimon Schubert #include "elf/common.h"
325796c8dcSSimon Schubert 
335796c8dcSSimon Schubert #include <unistd.h>
345796c8dcSSimon Schubert #include <fcntl.h>
355796c8dcSSimon Schubert 
365796c8dcSSimon Schubert 
37*cf7f2e2dSJohn Marino /* This function handles access via /proc/PID/auxv, which is a common method
38*cf7f2e2dSJohn Marino    for native targets.  */
395796c8dcSSimon Schubert 
40*cf7f2e2dSJohn Marino static LONGEST
41*cf7f2e2dSJohn Marino procfs_xfer_auxv (gdb_byte *readbuf,
425796c8dcSSimon Schubert 		  const gdb_byte *writebuf,
435796c8dcSSimon Schubert 		  ULONGEST offset,
445796c8dcSSimon Schubert 		  LONGEST len)
455796c8dcSSimon Schubert {
465796c8dcSSimon Schubert   char *pathname;
475796c8dcSSimon Schubert   int fd;
485796c8dcSSimon Schubert   LONGEST n;
495796c8dcSSimon Schubert 
505796c8dcSSimon Schubert   pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid));
515796c8dcSSimon Schubert   fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY);
525796c8dcSSimon Schubert   xfree (pathname);
535796c8dcSSimon Schubert   if (fd < 0)
545796c8dcSSimon Schubert     return -1;
555796c8dcSSimon Schubert 
565796c8dcSSimon Schubert   if (offset != (ULONGEST) 0
575796c8dcSSimon Schubert       && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
585796c8dcSSimon Schubert     n = -1;
595796c8dcSSimon Schubert   else if (readbuf != NULL)
605796c8dcSSimon Schubert     n = read (fd, readbuf, len);
615796c8dcSSimon Schubert   else
625796c8dcSSimon Schubert     n = write (fd, writebuf, len);
635796c8dcSSimon Schubert 
645796c8dcSSimon Schubert   (void) close (fd);
655796c8dcSSimon Schubert 
665796c8dcSSimon Schubert   return n;
675796c8dcSSimon Schubert }
685796c8dcSSimon Schubert 
69*cf7f2e2dSJohn Marino /* This function handles access via ld.so's symbol `_dl_auxv'.  */
70*cf7f2e2dSJohn Marino 
71*cf7f2e2dSJohn Marino static LONGEST
72*cf7f2e2dSJohn Marino ld_so_xfer_auxv (gdb_byte *readbuf,
73*cf7f2e2dSJohn Marino 		 const gdb_byte *writebuf,
74*cf7f2e2dSJohn Marino 		 ULONGEST offset,
75*cf7f2e2dSJohn Marino 		 LONGEST len)
76*cf7f2e2dSJohn Marino {
77*cf7f2e2dSJohn Marino   struct minimal_symbol *msym;
78*cf7f2e2dSJohn Marino   CORE_ADDR data_address, pointer_address;
79*cf7f2e2dSJohn Marino   struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
80*cf7f2e2dSJohn Marino   size_t ptr_size = TYPE_LENGTH (ptr_type);
81*cf7f2e2dSJohn Marino   size_t auxv_pair_size = 2 * ptr_size;
82*cf7f2e2dSJohn Marino   gdb_byte *ptr_buf = alloca (ptr_size);
83*cf7f2e2dSJohn Marino   LONGEST retval;
84*cf7f2e2dSJohn Marino   size_t block;
85*cf7f2e2dSJohn Marino 
86*cf7f2e2dSJohn Marino   msym = lookup_minimal_symbol ("_dl_auxv", NULL, NULL);
87*cf7f2e2dSJohn Marino   if (msym == NULL)
88*cf7f2e2dSJohn Marino     return -1;
89*cf7f2e2dSJohn Marino 
90*cf7f2e2dSJohn Marino   if (MSYMBOL_SIZE (msym) != ptr_size)
91*cf7f2e2dSJohn Marino     return -1;
92*cf7f2e2dSJohn Marino 
93*cf7f2e2dSJohn Marino   /* POINTER_ADDRESS is a location where the `_dl_auxv' variable resides.
94*cf7f2e2dSJohn Marino      DATA_ADDRESS is the inferior value present in `_dl_auxv', therefore the
95*cf7f2e2dSJohn Marino      real inferior AUXV address.  */
96*cf7f2e2dSJohn Marino 
97*cf7f2e2dSJohn Marino   pointer_address = SYMBOL_VALUE_ADDRESS (msym);
98*cf7f2e2dSJohn Marino 
99*cf7f2e2dSJohn Marino   /* The location of the _dl_auxv symbol may no longer be correct if
100*cf7f2e2dSJohn Marino      ld.so runs at a different address than the one present in the file.
101*cf7f2e2dSJohn Marino      This is very common case - for unprelinked ld.so or with a PIE executable.
102*cf7f2e2dSJohn Marino      PIE executable forces random address even for libraries already being
103*cf7f2e2dSJohn Marino      prelinked to some address.  PIE executables themselves are never prelinked
104*cf7f2e2dSJohn Marino      even on prelinked systems.  Prelinking of a PIE executable would block
105*cf7f2e2dSJohn Marino      their purpose of randomizing load of everything including the executable.
106*cf7f2e2dSJohn Marino 
107*cf7f2e2dSJohn Marino      If the memory read fails, return -1 to fallback on another mechanism for
108*cf7f2e2dSJohn Marino      retrieving the AUXV.
109*cf7f2e2dSJohn Marino 
110*cf7f2e2dSJohn Marino      In most cases of a PIE running under valgrind there is no way to find
111*cf7f2e2dSJohn Marino      out the base addresses of any of ld.so, executable or AUXV as everything
112*cf7f2e2dSJohn Marino      is randomized and /proc information is not relevant for the virtual
113*cf7f2e2dSJohn Marino      executable running under valgrind.  We think that we might need a valgrind
114*cf7f2e2dSJohn Marino      extension to make it work.  This is PR 11440.  */
115*cf7f2e2dSJohn Marino 
116*cf7f2e2dSJohn Marino   if (target_read_memory (pointer_address, ptr_buf, ptr_size) != 0)
117*cf7f2e2dSJohn Marino     return -1;
118*cf7f2e2dSJohn Marino 
119*cf7f2e2dSJohn Marino   data_address = extract_typed_address (ptr_buf, ptr_type);
120*cf7f2e2dSJohn Marino 
121*cf7f2e2dSJohn Marino   /* Possibly still not initialized such as during an inferior startup.  */
122*cf7f2e2dSJohn Marino   if (data_address == 0)
123*cf7f2e2dSJohn Marino     return -1;
124*cf7f2e2dSJohn Marino 
125*cf7f2e2dSJohn Marino   data_address += offset;
126*cf7f2e2dSJohn Marino 
127*cf7f2e2dSJohn Marino   if (writebuf != NULL)
128*cf7f2e2dSJohn Marino     {
129*cf7f2e2dSJohn Marino       if (target_write_memory (data_address, writebuf, len) == 0)
130*cf7f2e2dSJohn Marino 	return len;
131*cf7f2e2dSJohn Marino       else
132*cf7f2e2dSJohn Marino 	return -1;
133*cf7f2e2dSJohn Marino     }
134*cf7f2e2dSJohn Marino 
135*cf7f2e2dSJohn Marino   /* Stop if trying to read past the existing AUXV block.  The final AT_NULL
136*cf7f2e2dSJohn Marino      was already returned before.  */
137*cf7f2e2dSJohn Marino 
138*cf7f2e2dSJohn Marino   if (offset >= auxv_pair_size)
139*cf7f2e2dSJohn Marino     {
140*cf7f2e2dSJohn Marino       if (target_read_memory (data_address - auxv_pair_size, ptr_buf,
141*cf7f2e2dSJohn Marino 			      ptr_size) != 0)
142*cf7f2e2dSJohn Marino 	return -1;
143*cf7f2e2dSJohn Marino 
144*cf7f2e2dSJohn Marino       if (extract_typed_address (ptr_buf, ptr_type) == AT_NULL)
145*cf7f2e2dSJohn Marino 	return 0;
146*cf7f2e2dSJohn Marino     }
147*cf7f2e2dSJohn Marino 
148*cf7f2e2dSJohn Marino   retval = 0;
149*cf7f2e2dSJohn Marino   block = 0x400;
150*cf7f2e2dSJohn Marino   gdb_assert (block % auxv_pair_size == 0);
151*cf7f2e2dSJohn Marino 
152*cf7f2e2dSJohn Marino   while (len > 0)
153*cf7f2e2dSJohn Marino     {
154*cf7f2e2dSJohn Marino       if (block > len)
155*cf7f2e2dSJohn Marino 	block = len;
156*cf7f2e2dSJohn Marino 
157*cf7f2e2dSJohn Marino       /* Reading sizes smaller than AUXV_PAIR_SIZE is not supported.  Tails
158*cf7f2e2dSJohn Marino 	 unaligned to AUXV_PAIR_SIZE will not be read during a call (they
159*cf7f2e2dSJohn Marino 	 should be completed during next read with new/extended buffer).  */
160*cf7f2e2dSJohn Marino 
161*cf7f2e2dSJohn Marino       block &= -auxv_pair_size;
162*cf7f2e2dSJohn Marino       if (block == 0)
163*cf7f2e2dSJohn Marino 	return retval;
164*cf7f2e2dSJohn Marino 
165*cf7f2e2dSJohn Marino       if (target_read_memory (data_address, readbuf, block) != 0)
166*cf7f2e2dSJohn Marino 	{
167*cf7f2e2dSJohn Marino 	  if (block <= auxv_pair_size)
168*cf7f2e2dSJohn Marino 	    return retval;
169*cf7f2e2dSJohn Marino 
170*cf7f2e2dSJohn Marino 	  block = auxv_pair_size;
171*cf7f2e2dSJohn Marino 	  continue;
172*cf7f2e2dSJohn Marino 	}
173*cf7f2e2dSJohn Marino 
174*cf7f2e2dSJohn Marino       data_address += block;
175*cf7f2e2dSJohn Marino       len -= block;
176*cf7f2e2dSJohn Marino 
177*cf7f2e2dSJohn Marino       /* Check terminal AT_NULL.  This function is being called indefinitely
178*cf7f2e2dSJohn Marino          being extended its READBUF until it returns EOF (0).  */
179*cf7f2e2dSJohn Marino 
180*cf7f2e2dSJohn Marino       while (block >= auxv_pair_size)
181*cf7f2e2dSJohn Marino 	{
182*cf7f2e2dSJohn Marino 	  retval += auxv_pair_size;
183*cf7f2e2dSJohn Marino 
184*cf7f2e2dSJohn Marino 	  if (extract_typed_address (readbuf, ptr_type) == AT_NULL)
185*cf7f2e2dSJohn Marino 	    return retval;
186*cf7f2e2dSJohn Marino 
187*cf7f2e2dSJohn Marino 	  readbuf += auxv_pair_size;
188*cf7f2e2dSJohn Marino 	  block -= auxv_pair_size;
189*cf7f2e2dSJohn Marino 	}
190*cf7f2e2dSJohn Marino     }
191*cf7f2e2dSJohn Marino 
192*cf7f2e2dSJohn Marino   return retval;
193*cf7f2e2dSJohn Marino }
194*cf7f2e2dSJohn Marino 
195*cf7f2e2dSJohn Marino /* This function is called like a to_xfer_partial hook, but must be
196*cf7f2e2dSJohn Marino    called with TARGET_OBJECT_AUXV.  It handles access to AUXV.  */
197*cf7f2e2dSJohn Marino 
198*cf7f2e2dSJohn Marino LONGEST
199*cf7f2e2dSJohn Marino memory_xfer_auxv (struct target_ops *ops,
200*cf7f2e2dSJohn Marino 		  enum target_object object,
201*cf7f2e2dSJohn Marino 		  const char *annex,
202*cf7f2e2dSJohn Marino 		  gdb_byte *readbuf,
203*cf7f2e2dSJohn Marino 		  const gdb_byte *writebuf,
204*cf7f2e2dSJohn Marino 		  ULONGEST offset,
205*cf7f2e2dSJohn Marino 		  LONGEST len)
206*cf7f2e2dSJohn Marino {
207*cf7f2e2dSJohn Marino   gdb_assert (object == TARGET_OBJECT_AUXV);
208*cf7f2e2dSJohn Marino   gdb_assert (readbuf || writebuf);
209*cf7f2e2dSJohn Marino 
210*cf7f2e2dSJohn Marino    /* ld_so_xfer_auxv is the only function safe for virtual executables being
211*cf7f2e2dSJohn Marino       executed by valgrind's memcheck.  Using ld_so_xfer_auxv during inferior
212*cf7f2e2dSJohn Marino       startup is problematic, because ld.so symbol tables have not yet been
213*cf7f2e2dSJohn Marino       relocated.  So GDB uses this function only when attaching to a process.
214*cf7f2e2dSJohn Marino       */
215*cf7f2e2dSJohn Marino 
216*cf7f2e2dSJohn Marino   if (current_inferior ()->attach_flag != 0)
217*cf7f2e2dSJohn Marino     {
218*cf7f2e2dSJohn Marino       LONGEST retval;
219*cf7f2e2dSJohn Marino 
220*cf7f2e2dSJohn Marino       retval = ld_so_xfer_auxv (readbuf, writebuf, offset, len);
221*cf7f2e2dSJohn Marino       if (retval != -1)
222*cf7f2e2dSJohn Marino 	return retval;
223*cf7f2e2dSJohn Marino     }
224*cf7f2e2dSJohn Marino 
225*cf7f2e2dSJohn Marino   return procfs_xfer_auxv (readbuf, writebuf, offset, len);
226*cf7f2e2dSJohn Marino }
227*cf7f2e2dSJohn Marino 
2285796c8dcSSimon Schubert /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
2295796c8dcSSimon Schubert    Return 0 if *READPTR is already at the end of the buffer.
2305796c8dcSSimon Schubert    Return -1 if there is insufficient buffer for a whole entry.
2315796c8dcSSimon Schubert    Return 1 if an entry was read into *TYPEP and *VALP.  */
2325796c8dcSSimon Schubert static int
2335796c8dcSSimon Schubert default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
2345796c8dcSSimon Schubert 		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
2355796c8dcSSimon Schubert {
2365796c8dcSSimon Schubert   const int sizeof_auxv_field = gdbarch_ptr_bit (target_gdbarch)
2375796c8dcSSimon Schubert 				/ TARGET_CHAR_BIT;
2385796c8dcSSimon Schubert   const enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
2395796c8dcSSimon Schubert   gdb_byte *ptr = *readptr;
2405796c8dcSSimon Schubert 
2415796c8dcSSimon Schubert   if (endptr == ptr)
2425796c8dcSSimon Schubert     return 0;
2435796c8dcSSimon Schubert 
2445796c8dcSSimon Schubert   if (endptr - ptr < sizeof_auxv_field * 2)
2455796c8dcSSimon Schubert     return -1;
2465796c8dcSSimon Schubert 
2475796c8dcSSimon Schubert   *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
2485796c8dcSSimon Schubert   ptr += sizeof_auxv_field;
2495796c8dcSSimon Schubert   *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
2505796c8dcSSimon Schubert   ptr += sizeof_auxv_field;
2515796c8dcSSimon Schubert 
2525796c8dcSSimon Schubert   *readptr = ptr;
2535796c8dcSSimon Schubert   return 1;
2545796c8dcSSimon Schubert }
2555796c8dcSSimon Schubert 
2565796c8dcSSimon Schubert /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
2575796c8dcSSimon Schubert    Return 0 if *READPTR is already at the end of the buffer.
2585796c8dcSSimon Schubert    Return -1 if there is insufficient buffer for a whole entry.
2595796c8dcSSimon Schubert    Return 1 if an entry was read into *TYPEP and *VALP.  */
2605796c8dcSSimon Schubert int
2615796c8dcSSimon Schubert target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
2625796c8dcSSimon Schubert                   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
2635796c8dcSSimon Schubert {
2645796c8dcSSimon Schubert   struct target_ops *t;
265*cf7f2e2dSJohn Marino 
2665796c8dcSSimon Schubert   for (t = ops; t != NULL; t = t->beneath)
2675796c8dcSSimon Schubert     if (t->to_auxv_parse != NULL)
2685796c8dcSSimon Schubert       return t->to_auxv_parse (t, readptr, endptr, typep, valp);
2695796c8dcSSimon Schubert 
2705796c8dcSSimon Schubert   return default_auxv_parse (ops, readptr, endptr, typep, valp);
2715796c8dcSSimon Schubert }
2725796c8dcSSimon Schubert 
2735796c8dcSSimon Schubert /* Extract the auxiliary vector entry with a_type matching MATCH.
2745796c8dcSSimon Schubert    Return zero if no such entry was found, or -1 if there was
2755796c8dcSSimon Schubert    an error getting the information.  On success, return 1 after
2765796c8dcSSimon Schubert    storing the entry's value field in *VALP.  */
2775796c8dcSSimon Schubert int
2785796c8dcSSimon Schubert target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
2795796c8dcSSimon Schubert {
2805796c8dcSSimon Schubert   CORE_ADDR type, val;
2815796c8dcSSimon Schubert   gdb_byte *data;
2825796c8dcSSimon Schubert   LONGEST n = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL, &data);
2835796c8dcSSimon Schubert   gdb_byte *ptr = data;
2845796c8dcSSimon Schubert 
2855796c8dcSSimon Schubert   if (n <= 0)
2865796c8dcSSimon Schubert     return n;
2875796c8dcSSimon Schubert 
2885796c8dcSSimon Schubert   while (1)
2895796c8dcSSimon Schubert     switch (target_auxv_parse (ops, &ptr, data + n, &type, &val))
2905796c8dcSSimon Schubert       {
2915796c8dcSSimon Schubert       case 1:			/* Here's an entry, check it.  */
2925796c8dcSSimon Schubert 	if (type == match)
2935796c8dcSSimon Schubert 	  {
2945796c8dcSSimon Schubert 	    xfree (data);
2955796c8dcSSimon Schubert 	    *valp = val;
2965796c8dcSSimon Schubert 	    return 1;
2975796c8dcSSimon Schubert 	  }
2985796c8dcSSimon Schubert 	break;
2995796c8dcSSimon Schubert       case 0:			/* End of the vector.  */
3005796c8dcSSimon Schubert 	xfree (data);
3015796c8dcSSimon Schubert 	return 0;
3025796c8dcSSimon Schubert       default:			/* Bogosity.  */
3035796c8dcSSimon Schubert 	xfree (data);
3045796c8dcSSimon Schubert 	return -1;
3055796c8dcSSimon Schubert       }
3065796c8dcSSimon Schubert 
3075796c8dcSSimon Schubert   /*NOTREACHED*/
3085796c8dcSSimon Schubert }
3095796c8dcSSimon Schubert 
3105796c8dcSSimon Schubert 
3115796c8dcSSimon Schubert /* Print the contents of the target's AUXV on the specified file. */
3125796c8dcSSimon Schubert int
3135796c8dcSSimon Schubert fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
3145796c8dcSSimon Schubert {
3155796c8dcSSimon Schubert   CORE_ADDR type, val;
3165796c8dcSSimon Schubert   gdb_byte *data;
3175796c8dcSSimon Schubert   LONGEST len = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL,
3185796c8dcSSimon Schubert 				   &data);
3195796c8dcSSimon Schubert   gdb_byte *ptr = data;
3205796c8dcSSimon Schubert   int ents = 0;
3215796c8dcSSimon Schubert 
3225796c8dcSSimon Schubert   if (len <= 0)
3235796c8dcSSimon Schubert     return len;
3245796c8dcSSimon Schubert 
3255796c8dcSSimon Schubert   while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
3265796c8dcSSimon Schubert     {
3275796c8dcSSimon Schubert       const char *name = "???";
3285796c8dcSSimon Schubert       const char *description = "";
3295796c8dcSSimon Schubert       enum { dec, hex, str } flavor = hex;
3305796c8dcSSimon Schubert 
3315796c8dcSSimon Schubert       switch (type)
3325796c8dcSSimon Schubert 	{
3335796c8dcSSimon Schubert #define TAG(tag, text, kind) \
3345796c8dcSSimon Schubert 	case tag: name = #tag; description = text; flavor = kind; break
3355796c8dcSSimon Schubert 	  TAG (AT_NULL, _("End of vector"), hex);
3365796c8dcSSimon Schubert 	  TAG (AT_IGNORE, _("Entry should be ignored"), hex);
3375796c8dcSSimon Schubert 	  TAG (AT_EXECFD, _("File descriptor of program"), dec);
3385796c8dcSSimon Schubert 	  TAG (AT_PHDR, _("Program headers for program"), hex);
3395796c8dcSSimon Schubert 	  TAG (AT_PHENT, _("Size of program header entry"), dec);
3405796c8dcSSimon Schubert 	  TAG (AT_PHNUM, _("Number of program headers"), dec);
3415796c8dcSSimon Schubert 	  TAG (AT_PAGESZ, _("System page size"), dec);
3425796c8dcSSimon Schubert 	  TAG (AT_BASE, _("Base address of interpreter"), hex);
3435796c8dcSSimon Schubert 	  TAG (AT_FLAGS, _("Flags"), hex);
3445796c8dcSSimon Schubert 	  TAG (AT_ENTRY, _("Entry point of program"), hex);
3455796c8dcSSimon Schubert 	  TAG (AT_NOTELF, _("Program is not ELF"), dec);
3465796c8dcSSimon Schubert 	  TAG (AT_UID, _("Real user ID"), dec);
3475796c8dcSSimon Schubert 	  TAG (AT_EUID, _("Effective user ID"), dec);
3485796c8dcSSimon Schubert 	  TAG (AT_GID, _("Real group ID"), dec);
3495796c8dcSSimon Schubert 	  TAG (AT_EGID, _("Effective group ID"), dec);
3505796c8dcSSimon Schubert 	  TAG (AT_CLKTCK, _("Frequency of times()"), dec);
3515796c8dcSSimon Schubert 	  TAG (AT_PLATFORM, _("String identifying platform"), str);
3525796c8dcSSimon Schubert 	  TAG (AT_HWCAP, _("Machine-dependent CPU capability hints"), hex);
3535796c8dcSSimon Schubert 	  TAG (AT_FPUCW, _("Used FPU control word"), dec);
3545796c8dcSSimon Schubert 	  TAG (AT_DCACHEBSIZE, _("Data cache block size"), dec);
3555796c8dcSSimon Schubert 	  TAG (AT_ICACHEBSIZE, _("Instruction cache block size"), dec);
3565796c8dcSSimon Schubert 	  TAG (AT_UCACHEBSIZE, _("Unified cache block size"), dec);
3575796c8dcSSimon Schubert 	  TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec);
3585796c8dcSSimon Schubert 	  TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str);
3595796c8dcSSimon Schubert 	  TAG (AT_RANDOM, _("Address of 16 random bytes"), hex);
3605796c8dcSSimon Schubert 	  TAG (AT_EXECFN, _("File name of executable"), str);
3615796c8dcSSimon Schubert 	  TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec);
3625796c8dcSSimon Schubert 	  TAG (AT_SYSINFO, _("Special system info/entry points"), hex);
3635796c8dcSSimon Schubert 	  TAG (AT_SYSINFO_EHDR, _("System-supplied DSO's ELF header"), hex);
3645796c8dcSSimon Schubert 	  TAG (AT_SUN_UID, _("Effective user ID"), dec);
3655796c8dcSSimon Schubert 	  TAG (AT_SUN_RUID, _("Real user ID"), dec);
3665796c8dcSSimon Schubert 	  TAG (AT_SUN_GID, _("Effective group ID"), dec);
3675796c8dcSSimon Schubert 	  TAG (AT_SUN_RGID, _("Real group ID"), dec);
3685796c8dcSSimon Schubert 	  TAG (AT_SUN_LDELF, _("Dynamic linker's ELF header"), hex);
3695796c8dcSSimon Schubert 	  TAG (AT_SUN_LDSHDR, _("Dynamic linker's section headers"), hex);
3705796c8dcSSimon Schubert 	  TAG (AT_SUN_LDNAME, _("String giving name of dynamic linker"), str);
3715796c8dcSSimon Schubert 	  TAG (AT_SUN_LPAGESZ, _("Large pagesize"), dec);
3725796c8dcSSimon Schubert 	  TAG (AT_SUN_PLATFORM, _("Platform name string"), str);
3735796c8dcSSimon Schubert 	  TAG (AT_SUN_HWCAP, _("Machine-dependent CPU capability hints"), hex);
3745796c8dcSSimon Schubert 	  TAG (AT_SUN_IFLUSH, _("Should flush icache?"), dec);
3755796c8dcSSimon Schubert 	  TAG (AT_SUN_CPU, _("CPU name string"), str);
3765796c8dcSSimon Schubert 	  TAG (AT_SUN_EMUL_ENTRY, _("COFF entry point address"), hex);
3775796c8dcSSimon Schubert 	  TAG (AT_SUN_EMUL_EXECFD, _("COFF executable file descriptor"), dec);
3785796c8dcSSimon Schubert 	  TAG (AT_SUN_EXECNAME,
3795796c8dcSSimon Schubert 	       _("Canonicalized file name given to execve"), str);
3805796c8dcSSimon Schubert 	  TAG (AT_SUN_MMU, _("String for name of MMU module"), str);
3815796c8dcSSimon Schubert 	  TAG (AT_SUN_LDDATA, _("Dynamic linker's data segment address"), hex);
3825796c8dcSSimon Schubert 	  TAG (AT_SUN_AUXFLAGS,
3835796c8dcSSimon Schubert 	       _("AF_SUN_ flags passed from the kernel"), hex);
3845796c8dcSSimon Schubert 	}
3855796c8dcSSimon Schubert 
3865796c8dcSSimon Schubert       fprintf_filtered (file, "%-4s %-20s %-30s ",
3875796c8dcSSimon Schubert 			plongest (type), name, description);
3885796c8dcSSimon Schubert       switch (flavor)
3895796c8dcSSimon Schubert 	{
3905796c8dcSSimon Schubert 	case dec:
3915796c8dcSSimon Schubert 	  fprintf_filtered (file, "%s\n", plongest (val));
3925796c8dcSSimon Schubert 	  break;
3935796c8dcSSimon Schubert 	case hex:
3945796c8dcSSimon Schubert 	  fprintf_filtered (file, "%s\n", paddress (target_gdbarch, val));
3955796c8dcSSimon Schubert 	  break;
3965796c8dcSSimon Schubert 	case str:
3975796c8dcSSimon Schubert 	  {
3985796c8dcSSimon Schubert 	    struct value_print_options opts;
399*cf7f2e2dSJohn Marino 
4005796c8dcSSimon Schubert 	    get_user_print_options (&opts);
4015796c8dcSSimon Schubert 	    if (opts.addressprint)
4025796c8dcSSimon Schubert 	      fprintf_filtered (file, "%s", paddress (target_gdbarch, val));
4035796c8dcSSimon Schubert 	    val_print_string (builtin_type (target_gdbarch)->builtin_char,
4045796c8dcSSimon Schubert 			      val, -1, file, &opts);
4055796c8dcSSimon Schubert 	    fprintf_filtered (file, "\n");
4065796c8dcSSimon Schubert 	  }
4075796c8dcSSimon Schubert 	  break;
4085796c8dcSSimon Schubert 	}
4095796c8dcSSimon Schubert       ++ents;
4105796c8dcSSimon Schubert       if (type == AT_NULL)
4115796c8dcSSimon Schubert 	break;
4125796c8dcSSimon Schubert     }
4135796c8dcSSimon Schubert 
4145796c8dcSSimon Schubert   xfree (data);
4155796c8dcSSimon Schubert 
4165796c8dcSSimon Schubert   return ents;
4175796c8dcSSimon Schubert }
4185796c8dcSSimon Schubert 
4195796c8dcSSimon Schubert static void
4205796c8dcSSimon Schubert info_auxv_command (char *cmd, int from_tty)
4215796c8dcSSimon Schubert {
4225796c8dcSSimon Schubert   if (! target_has_stack)
4235796c8dcSSimon Schubert     error (_("The program has no auxiliary information now."));
4245796c8dcSSimon Schubert   else
4255796c8dcSSimon Schubert     {
4265796c8dcSSimon Schubert       int ents = fprint_target_auxv (gdb_stdout, &current_target);
427*cf7f2e2dSJohn Marino 
4285796c8dcSSimon Schubert       if (ents < 0)
4295796c8dcSSimon Schubert 	error (_("No auxiliary vector found, or failed reading it."));
4305796c8dcSSimon Schubert       else if (ents == 0)
4315796c8dcSSimon Schubert 	error (_("Auxiliary vector is empty."));
4325796c8dcSSimon Schubert     }
4335796c8dcSSimon Schubert }
4345796c8dcSSimon Schubert 
4355796c8dcSSimon Schubert 
4365796c8dcSSimon Schubert extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */
4375796c8dcSSimon Schubert 
4385796c8dcSSimon Schubert void
4395796c8dcSSimon Schubert _initialize_auxv (void)
4405796c8dcSSimon Schubert {
4415796c8dcSSimon Schubert   add_info ("auxv", info_auxv_command,
4425796c8dcSSimon Schubert 	    _("Display the inferior's auxiliary vector.\n\
4435796c8dcSSimon Schubert This is information provided by the operating system at program startup."));
4445796c8dcSSimon Schubert }
445