1130803Smarcel/* Auxiliary vector support for GDB, the GNU debugger. 2130803Smarcel 3130803Smarcel Copyright 2004 Free Software Foundation, Inc. 4130803Smarcel 5130803Smarcel This file is part of GDB. 6130803Smarcel 7130803Smarcel This program is free software; you can redistribute it and/or modify 8130803Smarcel it under the terms of the GNU General Public License as published by 9130803Smarcel the Free Software Foundation; either version 2 of the License, or 10130803Smarcel (at your option) any later version. 11130803Smarcel 12130803Smarcel This program is distributed in the hope that it will be useful, 13130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 14130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15130803Smarcel GNU General Public License for more details. 16130803Smarcel 17130803Smarcel You should have received a copy of the GNU General Public License 18130803Smarcel along with this program; if not, write to the Free Software 19130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 20130803Smarcel Boston, MA 02111-1307, USA. */ 21130803Smarcel 22130803Smarcel#include "defs.h" 23130803Smarcel#include "target.h" 24130803Smarcel#include "gdbtypes.h" 25130803Smarcel#include "command.h" 26130803Smarcel#include "inferior.h" 27130803Smarcel#include "valprint.h" 28130803Smarcel#include "gdb_assert.h" 29130803Smarcel 30130803Smarcel#include "auxv.h" 31130803Smarcel#include "elf/common.h" 32130803Smarcel 33130803Smarcel#include <unistd.h> 34130803Smarcel#include <fcntl.h> 35130803Smarcel 36130803Smarcel 37130803Smarcel/* This function is called like a to_xfer_partial hook, 38130803Smarcel but must be called with TARGET_OBJECT_AUXV. 39130803Smarcel It handles access via /proc/PID/auxv, which is the common method. 40130803Smarcel This function is appropriate for doing: 41130803Smarcel #define NATIVE_XFER_AUXV procfs_xfer_auxv 42130803Smarcel for a native target that uses inftarg.c's child_xfer_partial hook. */ 43130803Smarcel 44130803SmarcelLONGEST 45130803Smarcelprocfs_xfer_auxv (struct target_ops *ops, 46130803Smarcel int /* enum target_object */ object, 47130803Smarcel const char *annex, 48130803Smarcel void *readbuf, 49130803Smarcel const void *writebuf, 50130803Smarcel ULONGEST offset, 51130803Smarcel LONGEST len) 52130803Smarcel{ 53130803Smarcel char *pathname; 54130803Smarcel int fd; 55130803Smarcel LONGEST n; 56130803Smarcel 57130803Smarcel gdb_assert (object == TARGET_OBJECT_AUXV); 58130803Smarcel gdb_assert (readbuf || writebuf); 59130803Smarcel 60130803Smarcel pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid)); 61130803Smarcel fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY); 62130803Smarcel xfree (pathname); 63130803Smarcel if (fd < 0) 64130803Smarcel return -1; 65130803Smarcel 66130803Smarcel if (offset != (ULONGEST) 0 67130803Smarcel && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset) 68130803Smarcel n = -1; 69130803Smarcel else if (readbuf != NULL) 70130803Smarcel n = read (fd, readbuf, len); 71130803Smarcel else 72130803Smarcel n = write (fd, writebuf, len); 73130803Smarcel 74130803Smarcel (void) close (fd); 75130803Smarcel 76130803Smarcel return n; 77130803Smarcel} 78130803Smarcel 79130803Smarcel/* Read all the auxv data into a contiguous xmalloc'd buffer, 80130803Smarcel stored in *DATA. Return the size in bytes of this data. 81130803Smarcel If zero, there is no data and *DATA is null. 82130803Smarcel if < 0, there was an error and *DATA is null. */ 83130803SmarcelLONGEST 84130803Smarceltarget_auxv_read (struct target_ops *ops, char **data) 85130803Smarcel{ 86130803Smarcel size_t auxv_alloc = 512, auxv_pos = 0; 87130803Smarcel char *auxv = xmalloc (auxv_alloc); 88130803Smarcel int n; 89130803Smarcel 90130803Smarcel while (1) 91130803Smarcel { 92130803Smarcel n = target_read_partial (ops, TARGET_OBJECT_AUXV, 93130803Smarcel NULL, &auxv[auxv_pos], 0, 94130803Smarcel auxv_alloc - auxv_pos); 95130803Smarcel if (n <= 0) 96130803Smarcel break; 97130803Smarcel auxv_pos += n; 98130803Smarcel if (auxv_pos < auxv_alloc) /* Read all there was. */ 99130803Smarcel break; 100130803Smarcel gdb_assert (auxv_pos == auxv_alloc); 101130803Smarcel auxv_alloc *= 2; 102130803Smarcel auxv = xrealloc (auxv, auxv_alloc); 103130803Smarcel } 104130803Smarcel 105130803Smarcel if (auxv_pos == 0) 106130803Smarcel { 107130803Smarcel xfree (auxv); 108130803Smarcel *data = NULL; 109130803Smarcel return n; 110130803Smarcel } 111130803Smarcel 112130803Smarcel *data = auxv; 113130803Smarcel return auxv_pos; 114130803Smarcel} 115130803Smarcel 116130803Smarcel/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR. 117130803Smarcel Return 0 if *READPTR is already at the end of the buffer. 118130803Smarcel Return -1 if there is insufficient buffer for a whole entry. 119130803Smarcel Return 1 if an entry was read into *TYPEP and *VALP. */ 120130803Smarcelint 121130803Smarceltarget_auxv_parse (struct target_ops *ops, char **readptr, char *endptr, 122130803Smarcel CORE_ADDR *typep, CORE_ADDR *valp) 123130803Smarcel{ 124130803Smarcel const int sizeof_auxv_field = TYPE_LENGTH (builtin_type_void_data_ptr); 125130803Smarcel char *ptr = *readptr; 126130803Smarcel 127130803Smarcel if (endptr == ptr) 128130803Smarcel return 0; 129130803Smarcel 130130803Smarcel if (endptr - ptr < sizeof_auxv_field * 2) 131130803Smarcel return -1; 132130803Smarcel 133130803Smarcel *typep = extract_unsigned_integer (ptr, sizeof_auxv_field); 134130803Smarcel ptr += sizeof_auxv_field; 135130803Smarcel *valp = extract_unsigned_integer (ptr, sizeof_auxv_field); 136130803Smarcel ptr += sizeof_auxv_field; 137130803Smarcel 138130803Smarcel *readptr = ptr; 139130803Smarcel return 1; 140130803Smarcel} 141130803Smarcel 142130803Smarcel/* Extract the auxiliary vector entry with a_type matching MATCH. 143130803Smarcel Return zero if no such entry was found, or -1 if there was 144130803Smarcel an error getting the information. On success, return 1 after 145130803Smarcel storing the entry's value field in *VALP. */ 146130803Smarcelint 147130803Smarceltarget_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp) 148130803Smarcel{ 149130803Smarcel CORE_ADDR type, val; 150130803Smarcel char *data; 151130803Smarcel int n = target_auxv_read (ops, &data); 152130803Smarcel char *ptr = data; 153130803Smarcel int ents = 0; 154130803Smarcel 155130803Smarcel if (n <= 0) 156130803Smarcel return n; 157130803Smarcel 158130803Smarcel while (1) 159130803Smarcel switch (target_auxv_parse (ops, &ptr, data + n, &type, &val)) 160130803Smarcel { 161130803Smarcel case 1: /* Here's an entry, check it. */ 162130803Smarcel if (type == match) 163130803Smarcel { 164130803Smarcel xfree (data); 165130803Smarcel *valp = val; 166130803Smarcel return 1; 167130803Smarcel } 168130803Smarcel break; 169130803Smarcel case 0: /* End of the vector. */ 170130803Smarcel xfree (data); 171130803Smarcel return 0; 172130803Smarcel default: /* Bogosity. */ 173130803Smarcel xfree (data); 174130803Smarcel return -1; 175130803Smarcel } 176130803Smarcel 177130803Smarcel /*NOTREACHED*/ 178130803Smarcel} 179130803Smarcel 180130803Smarcel 181130803Smarcel/* Print the contents of the target's AUXV on the specified file. */ 182130803Smarcelint 183130803Smarcelfprint_target_auxv (struct ui_file *file, struct target_ops *ops) 184130803Smarcel{ 185130803Smarcel CORE_ADDR type, val; 186130803Smarcel char *data; 187130803Smarcel int len = target_auxv_read (ops, &data); 188130803Smarcel char *ptr = data; 189130803Smarcel int ents = 0; 190130803Smarcel 191130803Smarcel if (len <= 0) 192130803Smarcel return len; 193130803Smarcel 194130803Smarcel while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0) 195130803Smarcel { 196130803Smarcel extern int addressprint; 197130803Smarcel const char *name = "???"; 198130803Smarcel const char *description = ""; 199130803Smarcel enum { dec, hex, str } flavor = hex; 200130803Smarcel 201130803Smarcel switch (type) 202130803Smarcel { 203130803Smarcel#define TAG(tag, text, kind) \ 204130803Smarcel case tag: name = #tag; description = text; flavor = kind; break 205130803Smarcel TAG (AT_NULL, "End of vector", hex); 206130803Smarcel TAG (AT_IGNORE, "Entry should be ignored", hex); 207130803Smarcel TAG (AT_EXECFD, "File descriptor of program", dec); 208130803Smarcel TAG (AT_PHDR, "Program headers for program", hex); 209130803Smarcel TAG (AT_PHENT, "Size of program header entry", dec); 210130803Smarcel TAG (AT_PHNUM, "Number of program headers", dec); 211130803Smarcel TAG (AT_PAGESZ, "System page size", dec); 212130803Smarcel TAG (AT_BASE, "Base address of interpreter", hex); 213130803Smarcel TAG (AT_FLAGS, "Flags", hex); 214130803Smarcel TAG (AT_ENTRY, "Entry point of program", hex); 215130803Smarcel TAG (AT_NOTELF, "Program is not ELF", dec); 216130803Smarcel TAG (AT_UID, "Real user ID", dec); 217130803Smarcel TAG (AT_EUID, "Effective user ID", dec); 218130803Smarcel TAG (AT_GID, "Real group ID", dec); 219130803Smarcel TAG (AT_EGID, "Effective group ID", dec); 220130803Smarcel TAG (AT_CLKTCK, "Frequency of times()", dec); 221130803Smarcel TAG (AT_PLATFORM, "String identifying platform", str); 222130803Smarcel TAG (AT_HWCAP, "Machine-dependent CPU capability hints", hex); 223130803Smarcel TAG (AT_FPUCW, "Used FPU control word", dec); 224130803Smarcel TAG (AT_DCACHEBSIZE, "Data cache block size", dec); 225130803Smarcel TAG (AT_ICACHEBSIZE, "Instruction cache block size", dec); 226130803Smarcel TAG (AT_UCACHEBSIZE, "Unified cache block size", dec); 227130803Smarcel TAG (AT_IGNOREPPC, "Entry should be ignored", dec); 228130803Smarcel TAG (AT_SYSINFO, "Special system info/entry points", hex); 229130803Smarcel TAG (AT_SYSINFO_EHDR, "System-supplied DSO's ELF header", hex); 230130803Smarcel TAG (AT_SECURE, "Boolean, was exec setuid-like?", dec); 231130803Smarcel TAG (AT_SUN_UID, "Effective user ID", dec); 232130803Smarcel TAG (AT_SUN_RUID, "Real user ID", dec); 233130803Smarcel TAG (AT_SUN_GID, "Effective group ID", dec); 234130803Smarcel TAG (AT_SUN_RGID, "Real group ID", dec); 235130803Smarcel TAG (AT_SUN_LDELF, "Dynamic linker's ELF header", hex); 236130803Smarcel TAG (AT_SUN_LDSHDR, "Dynamic linker's section headers", hex); 237130803Smarcel TAG (AT_SUN_LDNAME, "String giving name of dynamic linker", str); 238130803Smarcel TAG (AT_SUN_LPAGESZ, "Large pagesize", dec); 239130803Smarcel TAG (AT_SUN_PLATFORM, "Platform name string", str); 240130803Smarcel TAG (AT_SUN_HWCAP, "Machine-dependent CPU capability hints", hex); 241130803Smarcel TAG (AT_SUN_IFLUSH, "Should flush icache?", dec); 242130803Smarcel TAG (AT_SUN_CPU, "CPU name string", str); 243130803Smarcel TAG (AT_SUN_EMUL_ENTRY, "COFF entry point address", hex); 244130803Smarcel TAG (AT_SUN_EMUL_EXECFD, "COFF executable file descriptor", dec); 245130803Smarcel TAG (AT_SUN_EXECNAME, 246130803Smarcel "Canonicalized file name given to execve", str); 247130803Smarcel TAG (AT_SUN_MMU, "String for name of MMU module", str); 248130803Smarcel TAG (AT_SUN_LDDATA, "Dynamic linker's data segment address", hex); 249130803Smarcel } 250130803Smarcel 251130803Smarcel fprintf_filtered (file, "%-4s %-20s %-30s ", 252130803Smarcel paddr_d (type), name, description); 253130803Smarcel switch (flavor) 254130803Smarcel { 255130803Smarcel case dec: 256130803Smarcel fprintf_filtered (file, "%s\n", paddr_d (val)); 257130803Smarcel break; 258130803Smarcel case hex: 259130803Smarcel fprintf_filtered (file, "0x%s\n", paddr_nz (val)); 260130803Smarcel break; 261130803Smarcel case str: 262130803Smarcel if (addressprint) 263130803Smarcel fprintf_filtered (file, "0x%s", paddr_nz (val)); 264130803Smarcel val_print_string (val, -1, 1, file); 265130803Smarcel fprintf_filtered (file, "\n"); 266130803Smarcel break; 267130803Smarcel } 268130803Smarcel ++ents; 269130803Smarcel } 270130803Smarcel 271130803Smarcel xfree (data); 272130803Smarcel 273130803Smarcel return ents; 274130803Smarcel} 275130803Smarcel 276130803Smarcelstatic void 277130803Smarcelinfo_auxv_command (char *cmd, int from_tty) 278130803Smarcel{ 279130803Smarcel if (! target_has_stack) 280130803Smarcel error ("The program has no auxiliary information now."); 281130803Smarcel else 282130803Smarcel { 283130803Smarcel int ents = fprint_target_auxv (gdb_stdout, ¤t_target); 284130803Smarcel if (ents < 0) 285130803Smarcel error ("No auxiliary vector found, or failed reading it."); 286130803Smarcel else if (ents == 0) 287130803Smarcel error ("Auxiliary vector is empty."); 288130803Smarcel } 289130803Smarcel} 290130803Smarcel 291130803Smarcel 292130803Smarcelextern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */ 293130803Smarcel 294130803Smarcelvoid 295130803Smarcel_initialize_auxv (void) 296130803Smarcel{ 297130803Smarcel add_info ("auxv", info_auxv_command, 298130803Smarcel "Display the inferior's auxiliary vector.\n\ 299130803SmarcelThis is information provided by the operating system at program startup."); 300130803Smarcel} 301