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