gdb/auxv.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "target.h"
- #include "gdbtypes.h"
- #include "command.h"
- #include "inferior.h"
- #include "valprint.h"
- #include "gdbcore.h"
- #include "observer.h"
- #include "filestuff.h"
- #include "objfiles.h"
- #include "auxv.h"
- #include "elf/common.h"
- #include <unistd.h>
- #include <fcntl.h>
- static enum target_xfer_status
- procfs_xfer_auxv (gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset,
- ULONGEST len,
- ULONGEST *xfered_len)
- {
- char *pathname;
- int fd;
- ssize_t l;
- pathname = xstrprintf ("/proc/%d/auxv", ptid_get_pid (inferior_ptid));
- fd = gdb_open_cloexec (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY, 0);
- xfree (pathname);
- if (fd < 0)
- return TARGET_XFER_E_IO;
- if (offset != (ULONGEST) 0
- && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
- l = -1;
- else if (readbuf != NULL)
- l = read (fd, readbuf, (size_t) len);
- else
- l = write (fd, writebuf, (size_t) len);
- (void) close (fd);
- if (l < 0)
- return TARGET_XFER_E_IO;
- else if (l == 0)
- return TARGET_XFER_EOF;
- else
- {
- *xfered_len = (ULONGEST) l;
- return TARGET_XFER_OK;
- }
- }
- static enum target_xfer_status
- ld_so_xfer_auxv (gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset,
- ULONGEST len, ULONGEST *xfered_len)
- {
- struct bound_minimal_symbol msym;
- CORE_ADDR data_address, pointer_address;
- struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
- size_t ptr_size = TYPE_LENGTH (ptr_type);
- size_t auxv_pair_size = 2 * ptr_size;
- gdb_byte *ptr_buf = alloca (ptr_size);
- LONGEST retval;
- size_t block;
- msym = lookup_minimal_symbol ("_dl_auxv", NULL, NULL);
- if (msym.minsym == NULL)
- return TARGET_XFER_E_IO;
- if (MSYMBOL_SIZE (msym.minsym) != ptr_size)
- return TARGET_XFER_E_IO;
-
- pointer_address = BMSYMBOL_VALUE_ADDRESS (msym);
-
- if (target_read_memory (pointer_address, ptr_buf, ptr_size) != 0)
- return TARGET_XFER_E_IO;
- data_address = extract_typed_address (ptr_buf, ptr_type);
-
- if (data_address == 0)
- return TARGET_XFER_E_IO;
- data_address += offset;
- if (writebuf != NULL)
- {
- if (target_write_memory (data_address, writebuf, len) == 0)
- {
- *xfered_len = (ULONGEST) len;
- return TARGET_XFER_OK;
- }
- else
- return TARGET_XFER_E_IO;
- }
-
- if (offset >= auxv_pair_size)
- {
- if (target_read_memory (data_address - auxv_pair_size, ptr_buf,
- ptr_size) != 0)
- return TARGET_XFER_E_IO;
- if (extract_typed_address (ptr_buf, ptr_type) == AT_NULL)
- return TARGET_XFER_EOF;
- }
- retval = 0;
- block = 0x400;
- gdb_assert (block % auxv_pair_size == 0);
- while (len > 0)
- {
- if (block > len)
- block = len;
-
- block &= -auxv_pair_size;
- if (block == 0)
- break;
- if (target_read_memory (data_address, readbuf, block) != 0)
- {
- if (block <= auxv_pair_size)
- break;
- block = auxv_pair_size;
- continue;
- }
- data_address += block;
- len -= block;
-
- while (block >= auxv_pair_size)
- {
- retval += auxv_pair_size;
- if (extract_typed_address (readbuf, ptr_type) == AT_NULL)
- {
- *xfered_len = (ULONGEST) retval;
- return TARGET_XFER_OK;
- }
- readbuf += auxv_pair_size;
- block -= auxv_pair_size;
- }
- }
- *xfered_len = (ULONGEST) retval;
- return TARGET_XFER_OK;
- }
- enum target_xfer_status
- memory_xfer_auxv (struct target_ops *ops,
- enum target_object object,
- const char *annex,
- gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset,
- ULONGEST len, ULONGEST *xfered_len)
- {
- gdb_assert (object == TARGET_OBJECT_AUXV);
- gdb_assert (readbuf || writebuf);
-
- if (current_inferior ()->attach_flag != 0)
- {
- enum target_xfer_status ret;
- ret = ld_so_xfer_auxv (readbuf, writebuf, offset, len, xfered_len);
- if (ret != TARGET_XFER_E_IO)
- return ret;
- }
- return procfs_xfer_auxv (readbuf, writebuf, offset, len, xfered_len);
- }
- int
- default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
- gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
- {
- const int sizeof_auxv_field = gdbarch_ptr_bit (target_gdbarch ())
- / TARGET_CHAR_BIT;
- const enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- gdb_byte *ptr = *readptr;
- if (endptr == ptr)
- return 0;
- if (endptr - ptr < sizeof_auxv_field * 2)
- return -1;
- *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
- ptr += sizeof_auxv_field;
- *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
- ptr += sizeof_auxv_field;
- *readptr = ptr;
- return 1;
- }
- int
- target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
- gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
- {
- struct gdbarch *gdbarch = target_gdbarch();
- if (gdbarch_auxv_parse_p (gdbarch))
- return gdbarch_auxv_parse (gdbarch, readptr, endptr, typep, valp);
- return current_target.to_auxv_parse (¤t_target, readptr, endptr,
- typep, valp);
- }
- static const struct inferior_data *auxv_inferior_data;
- struct auxv_info
- {
- LONGEST length;
- gdb_byte *data;
- };
- static void
- auxv_inferior_data_cleanup (struct inferior *inf, void *arg)
- {
- struct auxv_info *info;
- info = inferior_data (inf, auxv_inferior_data);
- if (info != NULL)
- {
- xfree (info->data);
- xfree (info);
- set_inferior_data (inf, auxv_inferior_data, NULL);
- }
- }
- static void
- invalidate_auxv_cache_inf (struct inferior *inf)
- {
- auxv_inferior_data_cleanup (inf, NULL);
- }
- static void
- invalidate_auxv_cache (void)
- {
- invalidate_auxv_cache_inf (current_inferior ());
- }
- static struct auxv_info *
- get_auxv_inferior_data (struct target_ops *ops)
- {
- struct auxv_info *info;
- struct inferior *inf = current_inferior ();
- info = inferior_data (inf, auxv_inferior_data);
- if (info == NULL)
- {
- info = XCNEW (struct auxv_info);
- info->length = target_read_alloc (ops, TARGET_OBJECT_AUXV,
- NULL, &info->data);
- set_inferior_data (inf, auxv_inferior_data, info);
- }
- return info;
- }
- int
- target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
- {
- CORE_ADDR type, val;
- gdb_byte *data;
- gdb_byte *ptr;
- struct auxv_info *info;
- info = get_auxv_inferior_data (ops);
- data = info->data;
- ptr = data;
- if (info->length <= 0)
- return info->length;
- while (1)
- switch (target_auxv_parse (ops, &ptr, data + info->length, &type, &val))
- {
- case 1:
- if (type == match)
- {
- *valp = val;
- return 1;
- }
- break;
- case 0:
- return 0;
- default:
- return -1;
- }
-
- }
- int
- fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
- {
- CORE_ADDR type, val;
- gdb_byte *data;
- gdb_byte *ptr;
- struct auxv_info *info;
- int ents = 0;
- info = get_auxv_inferior_data (ops);
- data = info->data;
- ptr = data;
- if (info->length <= 0)
- return info->length;
- while (target_auxv_parse (ops, &ptr, data + info->length, &type, &val) > 0)
- {
- const char *name = "???";
- const char *description = "";
- enum { dec, hex, str } flavor = hex;
- switch (type)
- {
- #define TAG(tag, text, kind) \
- case tag: name = #tag; description = text; flavor = kind; break
- TAG (AT_NULL, _("End of vector"), hex);
- TAG (AT_IGNORE, _("Entry should be ignored"), hex);
- TAG (AT_EXECFD, _("File descriptor of program"), dec);
- TAG (AT_PHDR, _("Program headers for program"), hex);
- TAG (AT_PHENT, _("Size of program header entry"), dec);
- TAG (AT_PHNUM, _("Number of program headers"), dec);
- TAG (AT_PAGESZ, _("System page size"), dec);
- TAG (AT_BASE, _("Base address of interpreter"), hex);
- TAG (AT_FLAGS, _("Flags"), hex);
- TAG (AT_ENTRY, _("Entry point of program"), hex);
- TAG (AT_NOTELF, _("Program is not ELF"), dec);
- TAG (AT_UID, _("Real user ID"), dec);
- TAG (AT_EUID, _("Effective user ID"), dec);
- TAG (AT_GID, _("Real group ID"), dec);
- TAG (AT_EGID, _("Effective group ID"), dec);
- TAG (AT_CLKTCK, _("Frequency of times()"), dec);
- TAG (AT_PLATFORM, _("String identifying platform"), str);
- TAG (AT_HWCAP, _("Machine-dependent CPU capability hints"), hex);
- TAG (AT_FPUCW, _("Used FPU control word"), dec);
- TAG (AT_DCACHEBSIZE, _("Data cache block size"), dec);
- TAG (AT_ICACHEBSIZE, _("Instruction cache block size"), dec);
- TAG (AT_UCACHEBSIZE, _("Unified cache block size"), dec);
- TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec);
- TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str);
- TAG (AT_RANDOM, _("Address of 16 random bytes"), hex);
- TAG (AT_HWCAP2, _("Extension of AT_HWCAP"), hex);
- TAG (AT_EXECFN, _("File name of executable"), str);
- TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec);
- TAG (AT_SYSINFO, _("Special system info/entry points"), hex);
- TAG (AT_SYSINFO_EHDR, _("System-supplied DSO's ELF header"), hex);
- TAG (AT_L1I_CACHESHAPE, _("L1 Instruction cache information"), hex);
- TAG (AT_L1D_CACHESHAPE, _("L1 Data cache information"), hex);
- TAG (AT_L2_CACHESHAPE, _("L2 cache information"), hex);
- TAG (AT_L3_CACHESHAPE, _("L3 cache information"), hex);
- TAG (AT_SUN_UID, _("Effective user ID"), dec);
- TAG (AT_SUN_RUID, _("Real user ID"), dec);
- TAG (AT_SUN_GID, _("Effective group ID"), dec);
- TAG (AT_SUN_RGID, _("Real group ID"), dec);
- TAG (AT_SUN_LDELF, _("Dynamic linker's ELF header"), hex);
- TAG (AT_SUN_LDSHDR, _("Dynamic linker's section headers"), hex);
- TAG (AT_SUN_LDNAME, _("String giving name of dynamic linker"), str);
- TAG (AT_SUN_LPAGESZ, _("Large pagesize"), dec);
- TAG (AT_SUN_PLATFORM, _("Platform name string"), str);
- TAG (AT_SUN_HWCAP, _("Machine-dependent CPU capability hints"), hex);
- TAG (AT_SUN_IFLUSH, _("Should flush icache?"), dec);
- TAG (AT_SUN_CPU, _("CPU name string"), str);
- TAG (AT_SUN_EMUL_ENTRY, _("COFF entry point address"), hex);
- TAG (AT_SUN_EMUL_EXECFD, _("COFF executable file descriptor"), dec);
- TAG (AT_SUN_EXECNAME,
- _("Canonicalized file name given to execve"), str);
- TAG (AT_SUN_MMU, _("String for name of MMU module"), str);
- TAG (AT_SUN_LDDATA, _("Dynamic linker's data segment address"), hex);
- TAG (AT_SUN_AUXFLAGS,
- _("AF_SUN_ flags passed from the kernel"), hex);
- }
- fprintf_filtered (file, "%-4s %-20s %-30s ",
- plongest (type), name, description);
- switch (flavor)
- {
- case dec:
- fprintf_filtered (file, "%s\n", plongest (val));
- break;
- case hex:
- fprintf_filtered (file, "%s\n", paddress (target_gdbarch (), val));
- break;
- case str:
- {
- struct value_print_options opts;
- get_user_print_options (&opts);
- if (opts.addressprint)
- fprintf_filtered (file, "%s ", paddress (target_gdbarch (), val));
- val_print_string (builtin_type (target_gdbarch ())->builtin_char,
- NULL, val, -1, file, &opts);
- fprintf_filtered (file, "\n");
- }
- break;
- }
- ++ents;
- if (type == AT_NULL)
- break;
- }
- return ents;
- }
- static void
- info_auxv_command (char *cmd, int from_tty)
- {
- if (! target_has_stack)
- error (_("The program has no auxiliary information now."));
- else
- {
- int ents = fprint_target_auxv (gdb_stdout, ¤t_target);
- if (ents < 0)
- error (_("No auxiliary vector found, or failed reading it."));
- else if (ents == 0)
- error (_("Auxiliary vector is empty."));
- }
- }
- extern initialize_file_ftype _initialize_auxv;
- void
- _initialize_auxv (void)
- {
- add_info ("auxv", info_auxv_command,
- _("Display the inferior's auxiliary vector.\n\
- This is information provided by the operating system at program startup."));
-
- auxv_inferior_data
- = register_inferior_data_with_cleanup (NULL, auxv_inferior_data_cleanup);
-
- observer_attach_inferior_exit (invalidate_auxv_cache_inf);
- observer_attach_inferior_appeared (invalidate_auxv_cache_inf);
- observer_attach_executable_changed (invalidate_auxv_cache);
- }