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_field = TYPE_LENGTH (builtin_type_void_data_ptr); 125 char *ptr = *readptr; 126 127 if (endptr == ptr) 128 return 0; 129 130 if (endptr - ptr < sizeof_auxv_field * 2) 131 return -1; 132 133 *typep = extract_unsigned_integer (ptr, sizeof_auxv_field); 134 ptr += sizeof_auxv_field; 135 *valp = extract_unsigned_integer (ptr, sizeof_auxv_field); 136 ptr += sizeof_auxv_field; 137 138 *readptr = ptr; 139 return 1; 140} 141 142/* Extract the auxiliary vector entry with a_type matching MATCH. 143 Return zero if no such entry was found, or -1 if there was 144 an error getting the information. On success, return 1 after 145 storing the entry's value field in *VALP. */ 146int 147target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp) 148{ 149 CORE_ADDR type, val; 150 char *data; 151 int n = target_auxv_read (ops, &data); 152 char *ptr = data; 153 int ents = 0; 154 155 if (n <= 0) 156 return n; 157 158 while (1) 159 switch (target_auxv_parse (ops, &ptr, data + n, &type, &val)) 160 { 161 case 1: /* Here's an entry, check it. */ 162 if (type == match) 163 { 164 xfree (data); 165 *valp = val; 166 return 1; 167 } 168 break; 169 case 0: /* End of the vector. */ 170 xfree (data); 171 return 0; 172 default: /* Bogosity. */ 173 xfree (data); 174 return -1; 175 } 176 177 /*NOTREACHED*/ 178} 179 180 181/* Print the contents of the target's AUXV on the specified file. */ 182int 183fprint_target_auxv (struct ui_file *file, struct target_ops *ops) 184{ 185 CORE_ADDR type, val; 186 char *data; 187 int len = target_auxv_read (ops, &data); 188 char *ptr = data; 189 int ents = 0; 190 191 if (len <= 0) 192 return len; 193 194 while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0) 195 { 196 extern int addressprint; 197 const char *name = "???"; 198 const char *description = ""; 199 enum { dec, hex, str } flavor = hex; 200 201 switch (type) 202 { 203#define TAG(tag, text, kind) \ 204 case tag: name = #tag; description = text; flavor = kind; break 205 TAG (AT_NULL, "End of vector", hex); 206 TAG (AT_IGNORE, "Entry should be ignored", hex); 207 TAG (AT_EXECFD, "File descriptor of program", dec); 208 TAG (AT_PHDR, "Program headers for program", hex); 209 TAG (AT_PHENT, "Size of program header entry", dec); 210 TAG (AT_PHNUM, "Number of program headers", dec); 211 TAG (AT_PAGESZ, "System page size", dec); 212 TAG (AT_BASE, "Base address of interpreter", hex); 213 TAG (AT_FLAGS, "Flags", hex); 214 TAG (AT_ENTRY, "Entry point of program", hex); 215 TAG (AT_NOTELF, "Program is not ELF", dec); 216 TAG (AT_UID, "Real user ID", dec); 217 TAG (AT_EUID, "Effective user ID", dec); 218 TAG (AT_GID, "Real group ID", dec); 219 TAG (AT_EGID, "Effective group ID", dec); 220 TAG (AT_CLKTCK, "Frequency of times()", dec); 221 TAG (AT_PLATFORM, "String identifying platform", str); 222 TAG (AT_HWCAP, "Machine-dependent CPU capability hints", hex); 223 TAG (AT_FPUCW, "Used FPU control word", dec); 224 TAG (AT_DCACHEBSIZE, "Data cache block size", dec); 225 TAG (AT_ICACHEBSIZE, "Instruction cache block size", dec); 226 TAG (AT_UCACHEBSIZE, "Unified cache block size", dec); 227 TAG (AT_IGNOREPPC, "Entry should be ignored", dec); 228 TAG (AT_SYSINFO, "Special system info/entry points", hex); 229 TAG (AT_SYSINFO_EHDR, "System-supplied DSO's ELF header", hex); 230 TAG (AT_SECURE, "Boolean, was exec setuid-like?", dec); 231 TAG (AT_SUN_UID, "Effective user ID", dec); 232 TAG (AT_SUN_RUID, "Real user ID", dec); 233 TAG (AT_SUN_GID, "Effective group ID", dec); 234 TAG (AT_SUN_RGID, "Real group ID", dec); 235 TAG (AT_SUN_LDELF, "Dynamic linker's ELF header", hex); 236 TAG (AT_SUN_LDSHDR, "Dynamic linker's section headers", hex); 237 TAG (AT_SUN_LDNAME, "String giving name of dynamic linker", str); 238 TAG (AT_SUN_LPAGESZ, "Large pagesize", dec); 239 TAG (AT_SUN_PLATFORM, "Platform name string", str); 240 TAG (AT_SUN_HWCAP, "Machine-dependent CPU capability hints", hex); 241 TAG (AT_SUN_IFLUSH, "Should flush icache?", dec); 242 TAG (AT_SUN_CPU, "CPU name string", str); 243 TAG (AT_SUN_EMUL_ENTRY, "COFF entry point address", hex); 244 TAG (AT_SUN_EMUL_EXECFD, "COFF executable file descriptor", dec); 245 TAG (AT_SUN_EXECNAME, 246 "Canonicalized file name given to execve", str); 247 TAG (AT_SUN_MMU, "String for name of MMU module", str); 248 TAG (AT_SUN_LDDATA, "Dynamic linker's data segment address", hex); 249 } 250 251 fprintf_filtered (file, "%-4s %-20s %-30s ", 252 paddr_d (type), name, description); 253 switch (flavor) 254 { 255 case dec: 256 fprintf_filtered (file, "%s\n", paddr_d (val)); 257 break; 258 case hex: 259 fprintf_filtered (file, "0x%s\n", paddr_nz (val)); 260 break; 261 case str: 262 if (addressprint) 263 fprintf_filtered (file, "0x%s", paddr_nz (val)); 264 val_print_string (val, -1, 1, file); 265 fprintf_filtered (file, "\n"); 266 break; 267 } 268 ++ents; 269 } 270 271 xfree (data); 272 273 return ents; 274} 275 276static void 277info_auxv_command (char *cmd, int from_tty) 278{ 279 if (! target_has_stack) 280 error ("The program has no auxiliary information now."); 281 else 282 { 283 int ents = fprint_target_auxv (gdb_stdout, ¤t_target); 284 if (ents < 0) 285 error ("No auxiliary vector found, or failed reading it."); 286 else if (ents == 0) 287 error ("Auxiliary vector is empty."); 288 } 289} 290 291 292extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */ 293 294void 295_initialize_auxv (void) 296{ 297 add_info ("auxv", info_auxv_command, 298 "Display the inferior's auxiliary vector.\n\ 299This is information provided by the operating system at program startup."); 300} 301