15796c8dcSSimon Schubert /* Auxiliary vector support for GDB, the GNU debugger.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 2004-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GDB.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert (at your option) any later version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155796c8dcSSimon Schubert GNU General Public License for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
195796c8dcSSimon Schubert
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "target.h"
225796c8dcSSimon Schubert #include "gdbtypes.h"
235796c8dcSSimon Schubert #include "command.h"
245796c8dcSSimon Schubert #include "inferior.h"
255796c8dcSSimon Schubert #include "valprint.h"
265796c8dcSSimon Schubert #include "gdb_assert.h"
27cf7f2e2dSJohn Marino #include "gdbcore.h"
28a45ae5f8SJohn Marino #include "observer.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
37c50c785cSJohn Marino /* This function handles access via /proc/PID/auxv, which is a common
38c50c785cSJohn Marino method for native targets. */
395796c8dcSSimon Schubert
40cf7f2e2dSJohn Marino static LONGEST
procfs_xfer_auxv(gdb_byte * readbuf,const gdb_byte * writebuf,ULONGEST offset,LONGEST len)41cf7f2e2dSJohn 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
69cf7f2e2dSJohn Marino /* This function handles access via ld.so's symbol `_dl_auxv'. */
70cf7f2e2dSJohn Marino
71cf7f2e2dSJohn Marino static LONGEST
ld_so_xfer_auxv(gdb_byte * readbuf,const gdb_byte * writebuf,ULONGEST offset,LONGEST len)72cf7f2e2dSJohn Marino ld_so_xfer_auxv (gdb_byte *readbuf,
73cf7f2e2dSJohn Marino const gdb_byte *writebuf,
74cf7f2e2dSJohn Marino ULONGEST offset,
75cf7f2e2dSJohn Marino LONGEST len)
76cf7f2e2dSJohn Marino {
77cf7f2e2dSJohn Marino struct minimal_symbol *msym;
78cf7f2e2dSJohn Marino CORE_ADDR data_address, pointer_address;
79*ef5ccd6cSJohn Marino struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
80cf7f2e2dSJohn Marino size_t ptr_size = TYPE_LENGTH (ptr_type);
81cf7f2e2dSJohn Marino size_t auxv_pair_size = 2 * ptr_size;
82cf7f2e2dSJohn Marino gdb_byte *ptr_buf = alloca (ptr_size);
83cf7f2e2dSJohn Marino LONGEST retval;
84cf7f2e2dSJohn Marino size_t block;
85cf7f2e2dSJohn Marino
86cf7f2e2dSJohn Marino msym = lookup_minimal_symbol ("_dl_auxv", NULL, NULL);
87cf7f2e2dSJohn Marino if (msym == NULL)
88cf7f2e2dSJohn Marino return -1;
89cf7f2e2dSJohn Marino
90cf7f2e2dSJohn Marino if (MSYMBOL_SIZE (msym) != ptr_size)
91cf7f2e2dSJohn Marino return -1;
92cf7f2e2dSJohn Marino
93c50c785cSJohn Marino /* POINTER_ADDRESS is a location where the `_dl_auxv' variable
94c50c785cSJohn Marino resides. DATA_ADDRESS is the inferior value present in
95c50c785cSJohn Marino `_dl_auxv', therefore the real inferior AUXV address. */
96cf7f2e2dSJohn Marino
97cf7f2e2dSJohn Marino pointer_address = SYMBOL_VALUE_ADDRESS (msym);
98cf7f2e2dSJohn Marino
99cf7f2e2dSJohn Marino /* The location of the _dl_auxv symbol may no longer be correct if
100c50c785cSJohn Marino ld.so runs at a different address than the one present in the
101c50c785cSJohn Marino file. This is very common case - for unprelinked ld.so or with a
102c50c785cSJohn Marino PIE executable. PIE executable forces random address even for
103c50c785cSJohn Marino libraries already being prelinked to some address. PIE
104c50c785cSJohn Marino executables themselves are never prelinked even on prelinked
105c50c785cSJohn Marino systems. Prelinking of a PIE executable would block their
106c50c785cSJohn Marino purpose of randomizing load of everything including the
107c50c785cSJohn Marino executable.
108cf7f2e2dSJohn Marino
109c50c785cSJohn Marino If the memory read fails, return -1 to fallback on another
110c50c785cSJohn Marino mechanism for retrieving the AUXV.
111cf7f2e2dSJohn Marino
112c50c785cSJohn Marino In most cases of a PIE running under valgrind there is no way to
113c50c785cSJohn Marino find out the base addresses of any of ld.so, executable or AUXV
114c50c785cSJohn Marino as everything is randomized and /proc information is not relevant
115c50c785cSJohn Marino for the virtual executable running under valgrind. We think that
116c50c785cSJohn Marino we might need a valgrind extension to make it work. This is PR
117c50c785cSJohn Marino 11440. */
118cf7f2e2dSJohn Marino
119cf7f2e2dSJohn Marino if (target_read_memory (pointer_address, ptr_buf, ptr_size) != 0)
120cf7f2e2dSJohn Marino return -1;
121cf7f2e2dSJohn Marino
122cf7f2e2dSJohn Marino data_address = extract_typed_address (ptr_buf, ptr_type);
123cf7f2e2dSJohn Marino
124c50c785cSJohn Marino /* Possibly still not initialized such as during an inferior
125c50c785cSJohn Marino startup. */
126cf7f2e2dSJohn Marino if (data_address == 0)
127cf7f2e2dSJohn Marino return -1;
128cf7f2e2dSJohn Marino
129cf7f2e2dSJohn Marino data_address += offset;
130cf7f2e2dSJohn Marino
131cf7f2e2dSJohn Marino if (writebuf != NULL)
132cf7f2e2dSJohn Marino {
133cf7f2e2dSJohn Marino if (target_write_memory (data_address, writebuf, len) == 0)
134cf7f2e2dSJohn Marino return len;
135cf7f2e2dSJohn Marino else
136cf7f2e2dSJohn Marino return -1;
137cf7f2e2dSJohn Marino }
138cf7f2e2dSJohn Marino
139c50c785cSJohn Marino /* Stop if trying to read past the existing AUXV block. The final
140c50c785cSJohn Marino AT_NULL was already returned before. */
141cf7f2e2dSJohn Marino
142cf7f2e2dSJohn Marino if (offset >= auxv_pair_size)
143cf7f2e2dSJohn Marino {
144cf7f2e2dSJohn Marino if (target_read_memory (data_address - auxv_pair_size, ptr_buf,
145cf7f2e2dSJohn Marino ptr_size) != 0)
146cf7f2e2dSJohn Marino return -1;
147cf7f2e2dSJohn Marino
148cf7f2e2dSJohn Marino if (extract_typed_address (ptr_buf, ptr_type) == AT_NULL)
149cf7f2e2dSJohn Marino return 0;
150cf7f2e2dSJohn Marino }
151cf7f2e2dSJohn Marino
152cf7f2e2dSJohn Marino retval = 0;
153cf7f2e2dSJohn Marino block = 0x400;
154cf7f2e2dSJohn Marino gdb_assert (block % auxv_pair_size == 0);
155cf7f2e2dSJohn Marino
156cf7f2e2dSJohn Marino while (len > 0)
157cf7f2e2dSJohn Marino {
158cf7f2e2dSJohn Marino if (block > len)
159cf7f2e2dSJohn Marino block = len;
160cf7f2e2dSJohn Marino
161c50c785cSJohn Marino /* Reading sizes smaller than AUXV_PAIR_SIZE is not supported.
162c50c785cSJohn Marino Tails unaligned to AUXV_PAIR_SIZE will not be read during a
163c50c785cSJohn Marino call (they should be completed during next read with
164c50c785cSJohn Marino new/extended buffer). */
165cf7f2e2dSJohn Marino
166cf7f2e2dSJohn Marino block &= -auxv_pair_size;
167cf7f2e2dSJohn Marino if (block == 0)
168cf7f2e2dSJohn Marino return retval;
169cf7f2e2dSJohn Marino
170cf7f2e2dSJohn Marino if (target_read_memory (data_address, readbuf, block) != 0)
171cf7f2e2dSJohn Marino {
172cf7f2e2dSJohn Marino if (block <= auxv_pair_size)
173cf7f2e2dSJohn Marino return retval;
174cf7f2e2dSJohn Marino
175cf7f2e2dSJohn Marino block = auxv_pair_size;
176cf7f2e2dSJohn Marino continue;
177cf7f2e2dSJohn Marino }
178cf7f2e2dSJohn Marino
179cf7f2e2dSJohn Marino data_address += block;
180cf7f2e2dSJohn Marino len -= block;
181cf7f2e2dSJohn Marino
182c50c785cSJohn Marino /* Check terminal AT_NULL. This function is being called
183c50c785cSJohn Marino indefinitely being extended its READBUF until it returns EOF
184c50c785cSJohn Marino (0). */
185cf7f2e2dSJohn Marino
186cf7f2e2dSJohn Marino while (block >= auxv_pair_size)
187cf7f2e2dSJohn Marino {
188cf7f2e2dSJohn Marino retval += auxv_pair_size;
189cf7f2e2dSJohn Marino
190cf7f2e2dSJohn Marino if (extract_typed_address (readbuf, ptr_type) == AT_NULL)
191cf7f2e2dSJohn Marino return retval;
192cf7f2e2dSJohn Marino
193cf7f2e2dSJohn Marino readbuf += auxv_pair_size;
194cf7f2e2dSJohn Marino block -= auxv_pair_size;
195cf7f2e2dSJohn Marino }
196cf7f2e2dSJohn Marino }
197cf7f2e2dSJohn Marino
198cf7f2e2dSJohn Marino return retval;
199cf7f2e2dSJohn Marino }
200cf7f2e2dSJohn Marino
201cf7f2e2dSJohn Marino /* This function is called like a to_xfer_partial hook, but must be
202cf7f2e2dSJohn Marino called with TARGET_OBJECT_AUXV. It handles access to AUXV. */
203cf7f2e2dSJohn Marino
204cf7f2e2dSJohn Marino LONGEST
memory_xfer_auxv(struct target_ops * ops,enum target_object object,const char * annex,gdb_byte * readbuf,const gdb_byte * writebuf,ULONGEST offset,LONGEST len)205cf7f2e2dSJohn Marino memory_xfer_auxv (struct target_ops *ops,
206cf7f2e2dSJohn Marino enum target_object object,
207cf7f2e2dSJohn Marino const char *annex,
208cf7f2e2dSJohn Marino gdb_byte *readbuf,
209cf7f2e2dSJohn Marino const gdb_byte *writebuf,
210cf7f2e2dSJohn Marino ULONGEST offset,
211cf7f2e2dSJohn Marino LONGEST len)
212cf7f2e2dSJohn Marino {
213cf7f2e2dSJohn Marino gdb_assert (object == TARGET_OBJECT_AUXV);
214cf7f2e2dSJohn Marino gdb_assert (readbuf || writebuf);
215cf7f2e2dSJohn Marino
216c50c785cSJohn Marino /* ld_so_xfer_auxv is the only function safe for virtual
217c50c785cSJohn Marino executables being executed by valgrind's memcheck. Using
218c50c785cSJohn Marino ld_so_xfer_auxv during inferior startup is problematic, because
219c50c785cSJohn Marino ld.so symbol tables have not yet been relocated. So GDB uses
220c50c785cSJohn Marino this function only when attaching to a process.
221cf7f2e2dSJohn Marino */
222cf7f2e2dSJohn Marino
223cf7f2e2dSJohn Marino if (current_inferior ()->attach_flag != 0)
224cf7f2e2dSJohn Marino {
225cf7f2e2dSJohn Marino LONGEST retval;
226cf7f2e2dSJohn Marino
227cf7f2e2dSJohn Marino retval = ld_so_xfer_auxv (readbuf, writebuf, offset, len);
228cf7f2e2dSJohn Marino if (retval != -1)
229cf7f2e2dSJohn Marino return retval;
230cf7f2e2dSJohn Marino }
231cf7f2e2dSJohn Marino
232cf7f2e2dSJohn Marino return procfs_xfer_auxv (readbuf, writebuf, offset, len);
233cf7f2e2dSJohn Marino }
234cf7f2e2dSJohn Marino
2355796c8dcSSimon Schubert /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
2365796c8dcSSimon Schubert Return 0 if *READPTR is already at the end of the buffer.
2375796c8dcSSimon Schubert Return -1 if there is insufficient buffer for a whole entry.
2385796c8dcSSimon Schubert Return 1 if an entry was read into *TYPEP and *VALP. */
2395796c8dcSSimon Schubert static int
default_auxv_parse(struct target_ops * ops,gdb_byte ** readptr,gdb_byte * endptr,CORE_ADDR * typep,CORE_ADDR * valp)2405796c8dcSSimon Schubert default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
2415796c8dcSSimon Schubert gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
2425796c8dcSSimon Schubert {
243*ef5ccd6cSJohn Marino const int sizeof_auxv_field = gdbarch_ptr_bit (target_gdbarch ())
2445796c8dcSSimon Schubert / TARGET_CHAR_BIT;
245*ef5ccd6cSJohn Marino const enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
2465796c8dcSSimon Schubert gdb_byte *ptr = *readptr;
2475796c8dcSSimon Schubert
2485796c8dcSSimon Schubert if (endptr == ptr)
2495796c8dcSSimon Schubert return 0;
2505796c8dcSSimon Schubert
2515796c8dcSSimon Schubert if (endptr - ptr < sizeof_auxv_field * 2)
2525796c8dcSSimon Schubert return -1;
2535796c8dcSSimon Schubert
2545796c8dcSSimon Schubert *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
2555796c8dcSSimon Schubert ptr += sizeof_auxv_field;
2565796c8dcSSimon Schubert *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
2575796c8dcSSimon Schubert ptr += sizeof_auxv_field;
2585796c8dcSSimon Schubert
2595796c8dcSSimon Schubert *readptr = ptr;
2605796c8dcSSimon Schubert return 1;
2615796c8dcSSimon Schubert }
2625796c8dcSSimon Schubert
2635796c8dcSSimon Schubert /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
2645796c8dcSSimon Schubert Return 0 if *READPTR is already at the end of the buffer.
2655796c8dcSSimon Schubert Return -1 if there is insufficient buffer for a whole entry.
2665796c8dcSSimon Schubert Return 1 if an entry was read into *TYPEP and *VALP. */
2675796c8dcSSimon Schubert int
target_auxv_parse(struct target_ops * ops,gdb_byte ** readptr,gdb_byte * endptr,CORE_ADDR * typep,CORE_ADDR * valp)2685796c8dcSSimon Schubert target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
2695796c8dcSSimon Schubert gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
2705796c8dcSSimon Schubert {
2715796c8dcSSimon Schubert struct target_ops *t;
272cf7f2e2dSJohn Marino
2735796c8dcSSimon Schubert for (t = ops; t != NULL; t = t->beneath)
2745796c8dcSSimon Schubert if (t->to_auxv_parse != NULL)
2755796c8dcSSimon Schubert return t->to_auxv_parse (t, readptr, endptr, typep, valp);
2765796c8dcSSimon Schubert
2775796c8dcSSimon Schubert return default_auxv_parse (ops, readptr, endptr, typep, valp);
2785796c8dcSSimon Schubert }
2795796c8dcSSimon Schubert
280a45ae5f8SJohn Marino
281a45ae5f8SJohn Marino /* Per-inferior data key for auxv. */
282a45ae5f8SJohn Marino static const struct inferior_data *auxv_inferior_data;
283a45ae5f8SJohn Marino
284a45ae5f8SJohn Marino /* Auxiliary Vector information structure. This is used by GDB
285a45ae5f8SJohn Marino for caching purposes for each inferior. This helps reduce the
286a45ae5f8SJohn Marino overhead of transfering data from a remote target to the local host. */
287a45ae5f8SJohn Marino struct auxv_info
288a45ae5f8SJohn Marino {
289a45ae5f8SJohn Marino LONGEST length;
290a45ae5f8SJohn Marino gdb_byte *data;
291a45ae5f8SJohn Marino };
292a45ae5f8SJohn Marino
293a45ae5f8SJohn Marino /* Handles the cleanup of the auxv cache for inferior INF. ARG is ignored.
294a45ae5f8SJohn Marino Frees whatever allocated space there is to be freed and sets INF's auxv cache
295a45ae5f8SJohn Marino data pointer to NULL.
296a45ae5f8SJohn Marino
297a45ae5f8SJohn Marino This function is called when the following events occur: inferior_appeared,
298a45ae5f8SJohn Marino inferior_exit and executable_changed. */
299a45ae5f8SJohn Marino
300a45ae5f8SJohn Marino static void
auxv_inferior_data_cleanup(struct inferior * inf,void * arg)301a45ae5f8SJohn Marino auxv_inferior_data_cleanup (struct inferior *inf, void *arg)
302a45ae5f8SJohn Marino {
303a45ae5f8SJohn Marino struct auxv_info *info;
304a45ae5f8SJohn Marino
305a45ae5f8SJohn Marino info = inferior_data (inf, auxv_inferior_data);
306a45ae5f8SJohn Marino if (info != NULL)
307a45ae5f8SJohn Marino {
308a45ae5f8SJohn Marino xfree (info->data);
309a45ae5f8SJohn Marino xfree (info);
310a45ae5f8SJohn Marino set_inferior_data (inf, auxv_inferior_data, NULL);
311a45ae5f8SJohn Marino }
312a45ae5f8SJohn Marino }
313a45ae5f8SJohn Marino
314a45ae5f8SJohn Marino /* Invalidate INF's auxv cache. */
315a45ae5f8SJohn Marino
316a45ae5f8SJohn Marino static void
invalidate_auxv_cache_inf(struct inferior * inf)317a45ae5f8SJohn Marino invalidate_auxv_cache_inf (struct inferior *inf)
318a45ae5f8SJohn Marino {
319a45ae5f8SJohn Marino auxv_inferior_data_cleanup (inf, NULL);
320a45ae5f8SJohn Marino }
321a45ae5f8SJohn Marino
322a45ae5f8SJohn Marino /* Invalidate current inferior's auxv cache. */
323a45ae5f8SJohn Marino
324a45ae5f8SJohn Marino static void
invalidate_auxv_cache(void)325a45ae5f8SJohn Marino invalidate_auxv_cache (void)
326a45ae5f8SJohn Marino {
327a45ae5f8SJohn Marino invalidate_auxv_cache_inf (current_inferior ());
328a45ae5f8SJohn Marino }
329a45ae5f8SJohn Marino
330a45ae5f8SJohn Marino /* Fetch the auxv object from inferior INF. If auxv is cached already,
331a45ae5f8SJohn Marino return a pointer to the cache. If not, fetch the auxv object from the
332a45ae5f8SJohn Marino target and cache it. This function always returns a valid INFO pointer. */
333a45ae5f8SJohn Marino
334a45ae5f8SJohn Marino static struct auxv_info *
get_auxv_inferior_data(struct target_ops * ops)335a45ae5f8SJohn Marino get_auxv_inferior_data (struct target_ops *ops)
336a45ae5f8SJohn Marino {
337a45ae5f8SJohn Marino struct auxv_info *info;
338a45ae5f8SJohn Marino struct inferior *inf = current_inferior ();
339a45ae5f8SJohn Marino
340a45ae5f8SJohn Marino info = inferior_data (inf, auxv_inferior_data);
341a45ae5f8SJohn Marino if (info == NULL)
342a45ae5f8SJohn Marino {
343a45ae5f8SJohn Marino info = XZALLOC (struct auxv_info);
344a45ae5f8SJohn Marino info->length = target_read_alloc (ops, TARGET_OBJECT_AUXV,
345a45ae5f8SJohn Marino NULL, &info->data);
346a45ae5f8SJohn Marino set_inferior_data (inf, auxv_inferior_data, info);
347a45ae5f8SJohn Marino }
348a45ae5f8SJohn Marino
349a45ae5f8SJohn Marino return info;
350a45ae5f8SJohn Marino }
351a45ae5f8SJohn Marino
3525796c8dcSSimon Schubert /* Extract the auxiliary vector entry with a_type matching MATCH.
3535796c8dcSSimon Schubert Return zero if no such entry was found, or -1 if there was
3545796c8dcSSimon Schubert an error getting the information. On success, return 1 after
3555796c8dcSSimon Schubert storing the entry's value field in *VALP. */
3565796c8dcSSimon Schubert int
target_auxv_search(struct target_ops * ops,CORE_ADDR match,CORE_ADDR * valp)3575796c8dcSSimon Schubert target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
3585796c8dcSSimon Schubert {
3595796c8dcSSimon Schubert CORE_ADDR type, val;
3605796c8dcSSimon Schubert gdb_byte *data;
361a45ae5f8SJohn Marino gdb_byte *ptr;
362a45ae5f8SJohn Marino struct auxv_info *info;
3635796c8dcSSimon Schubert
364a45ae5f8SJohn Marino info = get_auxv_inferior_data (ops);
365a45ae5f8SJohn Marino
366a45ae5f8SJohn Marino data = info->data;
367a45ae5f8SJohn Marino ptr = data;
368a45ae5f8SJohn Marino
369a45ae5f8SJohn Marino if (info->length <= 0)
370a45ae5f8SJohn Marino return info->length;
3715796c8dcSSimon Schubert
3725796c8dcSSimon Schubert while (1)
373a45ae5f8SJohn Marino switch (target_auxv_parse (ops, &ptr, data + info->length, &type, &val))
3745796c8dcSSimon Schubert {
3755796c8dcSSimon Schubert case 1: /* Here's an entry, check it. */
3765796c8dcSSimon Schubert if (type == match)
3775796c8dcSSimon Schubert {
3785796c8dcSSimon Schubert *valp = val;
3795796c8dcSSimon Schubert return 1;
3805796c8dcSSimon Schubert }
3815796c8dcSSimon Schubert break;
3825796c8dcSSimon Schubert case 0: /* End of the vector. */
3835796c8dcSSimon Schubert return 0;
3845796c8dcSSimon Schubert default: /* Bogosity. */
3855796c8dcSSimon Schubert return -1;
3865796c8dcSSimon Schubert }
3875796c8dcSSimon Schubert
3885796c8dcSSimon Schubert /*NOTREACHED*/
3895796c8dcSSimon Schubert }
3905796c8dcSSimon Schubert
3915796c8dcSSimon Schubert
3925796c8dcSSimon Schubert /* Print the contents of the target's AUXV on the specified file. */
3935796c8dcSSimon Schubert int
fprint_target_auxv(struct ui_file * file,struct target_ops * ops)3945796c8dcSSimon Schubert fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
3955796c8dcSSimon Schubert {
3965796c8dcSSimon Schubert CORE_ADDR type, val;
3975796c8dcSSimon Schubert gdb_byte *data;
398a45ae5f8SJohn Marino gdb_byte *ptr;
399a45ae5f8SJohn Marino struct auxv_info *info;
4005796c8dcSSimon Schubert int ents = 0;
4015796c8dcSSimon Schubert
402a45ae5f8SJohn Marino info = get_auxv_inferior_data (ops);
4035796c8dcSSimon Schubert
404a45ae5f8SJohn Marino data = info->data;
405a45ae5f8SJohn Marino ptr = data;
406a45ae5f8SJohn Marino if (info->length <= 0)
407a45ae5f8SJohn Marino return info->length;
408a45ae5f8SJohn Marino
409a45ae5f8SJohn Marino while (target_auxv_parse (ops, &ptr, data + info->length, &type, &val) > 0)
4105796c8dcSSimon Schubert {
4115796c8dcSSimon Schubert const char *name = "???";
4125796c8dcSSimon Schubert const char *description = "";
4135796c8dcSSimon Schubert enum { dec, hex, str } flavor = hex;
4145796c8dcSSimon Schubert
4155796c8dcSSimon Schubert switch (type)
4165796c8dcSSimon Schubert {
4175796c8dcSSimon Schubert #define TAG(tag, text, kind) \
4185796c8dcSSimon Schubert case tag: name = #tag; description = text; flavor = kind; break
4195796c8dcSSimon Schubert TAG (AT_NULL, _("End of vector"), hex);
4205796c8dcSSimon Schubert TAG (AT_IGNORE, _("Entry should be ignored"), hex);
4215796c8dcSSimon Schubert TAG (AT_EXECFD, _("File descriptor of program"), dec);
4225796c8dcSSimon Schubert TAG (AT_PHDR, _("Program headers for program"), hex);
4235796c8dcSSimon Schubert TAG (AT_PHENT, _("Size of program header entry"), dec);
4245796c8dcSSimon Schubert TAG (AT_PHNUM, _("Number of program headers"), dec);
4255796c8dcSSimon Schubert TAG (AT_PAGESZ, _("System page size"), dec);
4265796c8dcSSimon Schubert TAG (AT_BASE, _("Base address of interpreter"), hex);
4275796c8dcSSimon Schubert TAG (AT_FLAGS, _("Flags"), hex);
4285796c8dcSSimon Schubert TAG (AT_ENTRY, _("Entry point of program"), hex);
4295796c8dcSSimon Schubert TAG (AT_NOTELF, _("Program is not ELF"), dec);
4305796c8dcSSimon Schubert TAG (AT_UID, _("Real user ID"), dec);
4315796c8dcSSimon Schubert TAG (AT_EUID, _("Effective user ID"), dec);
4325796c8dcSSimon Schubert TAG (AT_GID, _("Real group ID"), dec);
4335796c8dcSSimon Schubert TAG (AT_EGID, _("Effective group ID"), dec);
4345796c8dcSSimon Schubert TAG (AT_CLKTCK, _("Frequency of times()"), dec);
4355796c8dcSSimon Schubert TAG (AT_PLATFORM, _("String identifying platform"), str);
4365796c8dcSSimon Schubert TAG (AT_HWCAP, _("Machine-dependent CPU capability hints"), hex);
4375796c8dcSSimon Schubert TAG (AT_FPUCW, _("Used FPU control word"), dec);
4385796c8dcSSimon Schubert TAG (AT_DCACHEBSIZE, _("Data cache block size"), dec);
4395796c8dcSSimon Schubert TAG (AT_ICACHEBSIZE, _("Instruction cache block size"), dec);
4405796c8dcSSimon Schubert TAG (AT_UCACHEBSIZE, _("Unified cache block size"), dec);
4415796c8dcSSimon Schubert TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec);
4425796c8dcSSimon Schubert TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str);
4435796c8dcSSimon Schubert TAG (AT_RANDOM, _("Address of 16 random bytes"), hex);
4445796c8dcSSimon Schubert TAG (AT_EXECFN, _("File name of executable"), str);
4455796c8dcSSimon Schubert TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec);
4465796c8dcSSimon Schubert TAG (AT_SYSINFO, _("Special system info/entry points"), hex);
4475796c8dcSSimon Schubert TAG (AT_SYSINFO_EHDR, _("System-supplied DSO's ELF header"), hex);
448*ef5ccd6cSJohn Marino TAG (AT_L1I_CACHESHAPE, _("L1 Instruction cache information"), hex);
449*ef5ccd6cSJohn Marino TAG (AT_L1D_CACHESHAPE, _("L1 Data cache information"), hex);
450*ef5ccd6cSJohn Marino TAG (AT_L2_CACHESHAPE, _("L2 cache information"), hex);
451*ef5ccd6cSJohn Marino TAG (AT_L3_CACHESHAPE, _("L3 cache information"), hex);
4525796c8dcSSimon Schubert TAG (AT_SUN_UID, _("Effective user ID"), dec);
4535796c8dcSSimon Schubert TAG (AT_SUN_RUID, _("Real user ID"), dec);
4545796c8dcSSimon Schubert TAG (AT_SUN_GID, _("Effective group ID"), dec);
4555796c8dcSSimon Schubert TAG (AT_SUN_RGID, _("Real group ID"), dec);
4565796c8dcSSimon Schubert TAG (AT_SUN_LDELF, _("Dynamic linker's ELF header"), hex);
4575796c8dcSSimon Schubert TAG (AT_SUN_LDSHDR, _("Dynamic linker's section headers"), hex);
4585796c8dcSSimon Schubert TAG (AT_SUN_LDNAME, _("String giving name of dynamic linker"), str);
4595796c8dcSSimon Schubert TAG (AT_SUN_LPAGESZ, _("Large pagesize"), dec);
4605796c8dcSSimon Schubert TAG (AT_SUN_PLATFORM, _("Platform name string"), str);
4615796c8dcSSimon Schubert TAG (AT_SUN_HWCAP, _("Machine-dependent CPU capability hints"), hex);
4625796c8dcSSimon Schubert TAG (AT_SUN_IFLUSH, _("Should flush icache?"), dec);
4635796c8dcSSimon Schubert TAG (AT_SUN_CPU, _("CPU name string"), str);
4645796c8dcSSimon Schubert TAG (AT_SUN_EMUL_ENTRY, _("COFF entry point address"), hex);
4655796c8dcSSimon Schubert TAG (AT_SUN_EMUL_EXECFD, _("COFF executable file descriptor"), dec);
4665796c8dcSSimon Schubert TAG (AT_SUN_EXECNAME,
4675796c8dcSSimon Schubert _("Canonicalized file name given to execve"), str);
4685796c8dcSSimon Schubert TAG (AT_SUN_MMU, _("String for name of MMU module"), str);
4695796c8dcSSimon Schubert TAG (AT_SUN_LDDATA, _("Dynamic linker's data segment address"), hex);
4705796c8dcSSimon Schubert TAG (AT_SUN_AUXFLAGS,
4715796c8dcSSimon Schubert _("AF_SUN_ flags passed from the kernel"), hex);
4725796c8dcSSimon Schubert }
4735796c8dcSSimon Schubert
4745796c8dcSSimon Schubert fprintf_filtered (file, "%-4s %-20s %-30s ",
4755796c8dcSSimon Schubert plongest (type), name, description);
4765796c8dcSSimon Schubert switch (flavor)
4775796c8dcSSimon Schubert {
4785796c8dcSSimon Schubert case dec:
4795796c8dcSSimon Schubert fprintf_filtered (file, "%s\n", plongest (val));
4805796c8dcSSimon Schubert break;
4815796c8dcSSimon Schubert case hex:
482*ef5ccd6cSJohn Marino fprintf_filtered (file, "%s\n", paddress (target_gdbarch (), val));
4835796c8dcSSimon Schubert break;
4845796c8dcSSimon Schubert case str:
4855796c8dcSSimon Schubert {
4865796c8dcSSimon Schubert struct value_print_options opts;
487cf7f2e2dSJohn Marino
4885796c8dcSSimon Schubert get_user_print_options (&opts);
4895796c8dcSSimon Schubert if (opts.addressprint)
490*ef5ccd6cSJohn Marino fprintf_filtered (file, "%s ", paddress (target_gdbarch (), val));
491*ef5ccd6cSJohn Marino val_print_string (builtin_type (target_gdbarch ())->builtin_char,
492c50c785cSJohn Marino NULL, val, -1, file, &opts);
4935796c8dcSSimon Schubert fprintf_filtered (file, "\n");
4945796c8dcSSimon Schubert }
4955796c8dcSSimon Schubert break;
4965796c8dcSSimon Schubert }
4975796c8dcSSimon Schubert ++ents;
4985796c8dcSSimon Schubert if (type == AT_NULL)
4995796c8dcSSimon Schubert break;
5005796c8dcSSimon Schubert }
5015796c8dcSSimon Schubert
5025796c8dcSSimon Schubert return ents;
5035796c8dcSSimon Schubert }
5045796c8dcSSimon Schubert
5055796c8dcSSimon Schubert static void
info_auxv_command(char * cmd,int from_tty)5065796c8dcSSimon Schubert info_auxv_command (char *cmd, int from_tty)
5075796c8dcSSimon Schubert {
5085796c8dcSSimon Schubert if (! target_has_stack)
5095796c8dcSSimon Schubert error (_("The program has no auxiliary information now."));
5105796c8dcSSimon Schubert else
5115796c8dcSSimon Schubert {
5125796c8dcSSimon Schubert int ents = fprint_target_auxv (gdb_stdout, ¤t_target);
513cf7f2e2dSJohn Marino
5145796c8dcSSimon Schubert if (ents < 0)
5155796c8dcSSimon Schubert error (_("No auxiliary vector found, or failed reading it."));
5165796c8dcSSimon Schubert else if (ents == 0)
5175796c8dcSSimon Schubert error (_("Auxiliary vector is empty."));
5185796c8dcSSimon Schubert }
5195796c8dcSSimon Schubert }
5205796c8dcSSimon Schubert
5215796c8dcSSimon Schubert
5225796c8dcSSimon Schubert extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */
5235796c8dcSSimon Schubert
5245796c8dcSSimon Schubert void
_initialize_auxv(void)5255796c8dcSSimon Schubert _initialize_auxv (void)
5265796c8dcSSimon Schubert {
5275796c8dcSSimon Schubert add_info ("auxv", info_auxv_command,
5285796c8dcSSimon Schubert _("Display the inferior's auxiliary vector.\n\
5295796c8dcSSimon Schubert This is information provided by the operating system at program startup."));
530a45ae5f8SJohn Marino
531a45ae5f8SJohn Marino /* Set an auxv cache per-inferior. */
532a45ae5f8SJohn Marino auxv_inferior_data
533*ef5ccd6cSJohn Marino = register_inferior_data_with_cleanup (NULL, auxv_inferior_data_cleanup);
534a45ae5f8SJohn Marino
535a45ae5f8SJohn Marino /* Observers used to invalidate the auxv cache when needed. */
536a45ae5f8SJohn Marino observer_attach_inferior_exit (invalidate_auxv_cache_inf);
537a45ae5f8SJohn Marino observer_attach_inferior_appeared (invalidate_auxv_cache_inf);
538a45ae5f8SJohn Marino observer_attach_executable_changed (invalidate_auxv_cache);
5395796c8dcSSimon Schubert }
540