]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/auxv.c
Fix for gdb.base/corefile.exp failure on Linux
[thirdparty/binutils-gdb.git] / gdb / auxv.c
CommitLineData
14ed0a8b
RM
1/* Auxiliary vector support for GDB, the GNU debugger.
2
9b254dd1 3 Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
14ed0a8b
RM
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
14ed0a8b
RM
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
14ed0a8b
RM
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 "gdb_assert.h"
27
28#include "auxv.h"
29#include "elf/common.h"
30
31#include <unistd.h>
32#include <fcntl.h>
33
34
35/* This function is called like a to_xfer_partial hook,
36 but must be called with TARGET_OBJECT_AUXV.
37 It handles access via /proc/PID/auxv, which is the common method.
38 This function is appropriate for doing:
39 #define NATIVE_XFER_AUXV procfs_xfer_auxv
40 for a native target that uses inftarg.c's child_xfer_partial hook. */
41
42LONGEST
43procfs_xfer_auxv (struct target_ops *ops,
44 int /* enum target_object */ object,
45 const char *annex,
36aa5e41
AC
46 gdb_byte *readbuf,
47 const gdb_byte *writebuf,
14ed0a8b
RM
48 ULONGEST offset,
49 LONGEST len)
50{
51 char *pathname;
52 int fd;
53 LONGEST n;
54
55 gdb_assert (object == TARGET_OBJECT_AUXV);
56 gdb_assert (readbuf || writebuf);
57
58 pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid));
59 fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY);
60 xfree (pathname);
61 if (fd < 0)
62 return -1;
63
64 if (offset != (ULONGEST) 0
65 && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
66 n = -1;
67 else if (readbuf != NULL)
68 n = read (fd, readbuf, len);
69 else
70 n = write (fd, writebuf, len);
71
72 (void) close (fd);
73
74 return n;
75}
76
14ed0a8b
RM
77/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
78 Return 0 if *READPTR is already at the end of the buffer.
79 Return -1 if there is insufficient buffer for a whole entry.
80 Return 1 if an entry was read into *TYPEP and *VALP. */
81int
c47ffbe3 82default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
36aa5e41 83 gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
14ed0a8b
RM
84{
85 const int sizeof_auxv_field = TYPE_LENGTH (builtin_type_void_data_ptr);
36aa5e41 86 gdb_byte *ptr = *readptr;
14ed0a8b
RM
87
88 if (endptr == ptr)
89 return 0;
90
91 if (endptr - ptr < sizeof_auxv_field * 2)
92 return -1;
93
94 *typep = extract_unsigned_integer (ptr, sizeof_auxv_field);
95 ptr += sizeof_auxv_field;
96 *valp = extract_unsigned_integer (ptr, sizeof_auxv_field);
97 ptr += sizeof_auxv_field;
98
99 *readptr = ptr;
100 return 1;
101}
102
c47ffbe3
VP
103/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
104 Return 0 if *READPTR is already at the end of the buffer.
105 Return -1 if there is insufficient buffer for a whole entry.
106 Return 1 if an entry was read into *TYPEP and *VALP. */
107int
108target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
109 gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
110{
111 struct target_ops *t;
112 for (t = ops; t != NULL; t = t->beneath)
113 if (t->to_auxv_parse != NULL)
114 return t->to_auxv_parse (t, readptr, endptr, typep, valp);
115
116 return default_auxv_parse (ops, readptr, endptr, typep, valp);
117}
118
14ed0a8b
RM
119/* Extract the auxiliary vector entry with a_type matching MATCH.
120 Return zero if no such entry was found, or -1 if there was
121 an error getting the information. On success, return 1 after
122 storing the entry's value field in *VALP. */
123int
124target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
125{
126 CORE_ADDR type, val;
36aa5e41 127 gdb_byte *data;
13547ab6 128 LONGEST n = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL, &data);
36aa5e41 129 gdb_byte *ptr = data;
14ed0a8b
RM
130 int ents = 0;
131
132 if (n <= 0)
133 return n;
134
135 while (1)
136 switch (target_auxv_parse (ops, &ptr, data + n, &type, &val))
137 {
138 case 1: /* Here's an entry, check it. */
139 if (type == match)
140 {
141 xfree (data);
142 *valp = val;
143 return 1;
144 }
145 break;
146 case 0: /* End of the vector. */
147 xfree (data);
148 return 0;
149 default: /* Bogosity. */
150 xfree (data);
151 return -1;
152 }
153
154 /*NOTREACHED*/
155}
156
157
158/* Print the contents of the target's AUXV on the specified file. */
159int
160fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
161{
162 CORE_ADDR type, val;
36aa5e41 163 gdb_byte *data;
13547ab6
DJ
164 LONGEST len = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL,
165 &data);
36aa5e41 166 gdb_byte *ptr = data;
14ed0a8b
RM
167 int ents = 0;
168
169 if (len <= 0)
170 return len;
171
172 while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
173 {
174 extern int addressprint;
175 const char *name = "???";
176 const char *description = "";
177 enum { dec, hex, str } flavor = hex;
178
179 switch (type)
180 {
181#define TAG(tag, text, kind) \
182 case tag: name = #tag; description = text; flavor = kind; break
edefbb7c
AC
183 TAG (AT_NULL, _("End of vector"), hex);
184 TAG (AT_IGNORE, _("Entry should be ignored"), hex);
185 TAG (AT_EXECFD, _("File descriptor of program"), dec);
186 TAG (AT_PHDR, _("Program headers for program"), hex);
187 TAG (AT_PHENT, _("Size of program header entry"), dec);
188 TAG (AT_PHNUM, _("Number of program headers"), dec);
189 TAG (AT_PAGESZ, _("System page size"), dec);
190 TAG (AT_BASE, _("Base address of interpreter"), hex);
191 TAG (AT_FLAGS, _("Flags"), hex);
192 TAG (AT_ENTRY, _("Entry point of program"), hex);
193 TAG (AT_NOTELF, _("Program is not ELF"), dec);
194 TAG (AT_UID, _("Real user ID"), dec);
195 TAG (AT_EUID, _("Effective user ID"), dec);
196 TAG (AT_GID, _("Real group ID"), dec);
197 TAG (AT_EGID, _("Effective group ID"), dec);
198 TAG (AT_CLKTCK, _("Frequency of times()"), dec);
199 TAG (AT_PLATFORM, _("String identifying platform"), str);
200 TAG (AT_HWCAP, _("Machine-dependent CPU capability hints"), hex);
201 TAG (AT_FPUCW, _("Used FPU control word"), dec);
202 TAG (AT_DCACHEBSIZE, _("Data cache block size"), dec);
203 TAG (AT_ICACHEBSIZE, _("Instruction cache block size"), dec);
204 TAG (AT_UCACHEBSIZE, _("Unified cache block size"), dec);
205 TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec);
206 TAG (AT_SYSINFO, _("Special system info/entry points"), hex);
207 TAG (AT_SYSINFO_EHDR, _("System-supplied DSO's ELF header"), hex);
208 TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec);
209 TAG (AT_SUN_UID, _("Effective user ID"), dec);
210 TAG (AT_SUN_RUID, _("Real user ID"), dec);
211 TAG (AT_SUN_GID, _("Effective group ID"), dec);
212 TAG (AT_SUN_RGID, _("Real group ID"), dec);
213 TAG (AT_SUN_LDELF, _("Dynamic linker's ELF header"), hex);
214 TAG (AT_SUN_LDSHDR, _("Dynamic linker's section headers"), hex);
215 TAG (AT_SUN_LDNAME, _("String giving name of dynamic linker"), str);
216 TAG (AT_SUN_LPAGESZ, _("Large pagesize"), dec);
217 TAG (AT_SUN_PLATFORM, _("Platform name string"), str);
218 TAG (AT_SUN_HWCAP, _("Machine-dependent CPU capability hints"), hex);
219 TAG (AT_SUN_IFLUSH, _("Should flush icache?"), dec);
220 TAG (AT_SUN_CPU, _("CPU name string"), str);
221 TAG (AT_SUN_EMUL_ENTRY, _("COFF entry point address"), hex);
222 TAG (AT_SUN_EMUL_EXECFD, _("COFF executable file descriptor"), dec);
14ed0a8b 223 TAG (AT_SUN_EXECNAME,
edefbb7c
AC
224 _("Canonicalized file name given to execve"), str);
225 TAG (AT_SUN_MMU, _("String for name of MMU module"), str);
226 TAG (AT_SUN_LDDATA, _("Dynamic linker's data segment address"), hex);
77d49ac6
MK
227 TAG (AT_SUN_AUXFLAGS,
228 _("AF_SUN_ flags passed from the kernel"), hex);
14ed0a8b
RM
229 }
230
231 fprintf_filtered (file, "%-4s %-20s %-30s ",
232 paddr_d (type), name, description);
233 switch (flavor)
234 {
235 case dec:
236 fprintf_filtered (file, "%s\n", paddr_d (val));
237 break;
238 case hex:
239 fprintf_filtered (file, "0x%s\n", paddr_nz (val));
240 break;
241 case str:
242 if (addressprint)
243 fprintf_filtered (file, "0x%s", paddr_nz (val));
244 val_print_string (val, -1, 1, file);
245 fprintf_filtered (file, "\n");
246 break;
247 }
248 ++ents;
249 }
250
251 xfree (data);
252
253 return ents;
254}
255
256static void
257info_auxv_command (char *cmd, int from_tty)
258{
14ed0a8b 259 if (! target_has_stack)
edefbb7c 260 error (_("The program has no auxiliary information now."));
14ed0a8b
RM
261 else
262 {
263 int ents = fprint_target_auxv (gdb_stdout, &current_target);
264 if (ents < 0)
edefbb7c 265 error (_("No auxiliary vector found, or failed reading it."));
14ed0a8b 266 else if (ents == 0)
edefbb7c 267 error (_("Auxiliary vector is empty."));
14ed0a8b
RM
268 }
269}
270
271
272extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */
273
274void
275_initialize_auxv (void)
276{
277 add_info ("auxv", info_auxv_command,
edefbb7c
AC
278 _("Display the inferior's auxiliary vector.\n\
279This is information provided by the operating system at program startup."));
14ed0a8b 280}