X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdb%2Fauxv.c;h=8710d2f0a10d719048220f26923bd6f58195d8c6;hb=10a93b604f84ef19c9a15656c3aaeefac82b4e58;hp=e2aeb214388a636f9a434e873fab158201d77618;hpb=f5656eadf4383cc733b96ff49ba8efbea6922ad3;p=platform%2Fupstream%2Fbinutils.git diff --git a/gdb/auxv.c b/gdb/auxv.c index e2aeb21..8710d2f 100644 --- a/gdb/auxv.c +++ b/gdb/auxv.c @@ -1,6 +1,6 @@ /* Auxiliary vector support for GDB, the GNU debugger. - Copyright (C) 2004-2012 Free Software Foundation, Inc. + Copyright (C) 2004-2014 Free Software Foundation, Inc. This file is part of GDB. @@ -23,9 +23,10 @@ #include "command.h" #include "inferior.h" #include "valprint.h" -#include "gdb_assert.h" #include "gdbcore.h" #include "observer.h" +#include "filestuff.h" +#include "objfiles.h" #include "auxv.h" #include "elf/common.h" @@ -34,47 +35,57 @@ #include -/* This function handles access via /proc/PID/auxv, which is a common - method for native targets. */ +/* Implement the to_xfer_partial target_ops method. This function + handles access via /proc/PID/auxv, which is a common method for + native targets. */ -static LONGEST +static enum target_xfer_status procfs_xfer_auxv (gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, - LONGEST len) + ULONGEST len, + ULONGEST *xfered_len) { char *pathname; int fd; - LONGEST n; + ssize_t l; - pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid)); - fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY); + 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 -1; + return TARGET_XFER_E_IO; if (offset != (ULONGEST) 0 && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset) - n = -1; + l = -1; else if (readbuf != NULL) - n = read (fd, readbuf, len); + l = read (fd, readbuf, (size_t) len); else - n = write (fd, writebuf, len); + l = write (fd, writebuf, (size_t) len); (void) close (fd); - return n; + 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; + } } /* This function handles access via ld.so's symbol `_dl_auxv'. */ -static LONGEST +static enum target_xfer_status ld_so_xfer_auxv (gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, - LONGEST len) + ULONGEST len, ULONGEST *xfered_len) { - struct minimal_symbol *msym; + 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); @@ -84,17 +95,17 @@ ld_so_xfer_auxv (gdb_byte *readbuf, size_t block; msym = lookup_minimal_symbol ("_dl_auxv", NULL, NULL); - if (msym == NULL) - return -1; + if (msym.minsym == NULL) + return TARGET_XFER_E_IO; - if (MSYMBOL_SIZE (msym) != ptr_size) - return -1; + if (MSYMBOL_SIZE (msym.minsym) != ptr_size) + return TARGET_XFER_E_IO; /* POINTER_ADDRESS is a location where the `_dl_auxv' variable resides. DATA_ADDRESS is the inferior value present in `_dl_auxv', therefore the real inferior AUXV address. */ - pointer_address = SYMBOL_VALUE_ADDRESS (msym); + pointer_address = BMSYMBOL_VALUE_ADDRESS (msym); /* The location of the _dl_auxv symbol may no longer be correct if ld.so runs at a different address than the one present in the @@ -117,23 +128,26 @@ ld_so_xfer_auxv (gdb_byte *readbuf, 11440. */ if (target_read_memory (pointer_address, ptr_buf, ptr_size) != 0) - return -1; + return TARGET_XFER_E_IO; data_address = extract_typed_address (ptr_buf, ptr_type); /* Possibly still not initialized such as during an inferior startup. */ if (data_address == 0) - return -1; + return TARGET_XFER_E_IO; data_address += offset; if (writebuf != NULL) { if (target_write_memory (data_address, writebuf, len) == 0) - return len; + { + *xfered_len = (ULONGEST) len; + return TARGET_XFER_OK; + } else - return -1; + return TARGET_XFER_E_IO; } /* Stop if trying to read past the existing AUXV block. The final @@ -143,10 +157,10 @@ ld_so_xfer_auxv (gdb_byte *readbuf, { if (target_read_memory (data_address - auxv_pair_size, ptr_buf, ptr_size) != 0) - return -1; + return TARGET_XFER_E_IO; if (extract_typed_address (ptr_buf, ptr_type) == AT_NULL) - return 0; + return TARGET_XFER_EOF; } retval = 0; @@ -165,12 +179,12 @@ ld_so_xfer_auxv (gdb_byte *readbuf, block &= -auxv_pair_size; if (block == 0) - return retval; + break; if (target_read_memory (data_address, readbuf, block) != 0) { if (block <= auxv_pair_size) - return retval; + break; block = auxv_pair_size; continue; @@ -188,27 +202,31 @@ ld_so_xfer_auxv (gdb_byte *readbuf, retval += auxv_pair_size; if (extract_typed_address (readbuf, ptr_type) == AT_NULL) - return retval; + { + *xfered_len = (ULONGEST) retval; + return TARGET_XFER_OK; + } readbuf += auxv_pair_size; block -= auxv_pair_size; } } - return retval; + *xfered_len = (ULONGEST) retval; + return TARGET_XFER_OK; } -/* This function is called like a to_xfer_partial hook, but must be - called with TARGET_OBJECT_AUXV. It handles access to AUXV. */ +/* Implement the to_xfer_partial target_ops method for + TARGET_OBJECT_AUXV. It handles access to AUXV. */ -LONGEST +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, - LONGEST len) + ULONGEST len, ULONGEST *xfered_len) { gdb_assert (object == TARGET_OBJECT_AUXV); gdb_assert (readbuf || writebuf); @@ -222,21 +240,21 @@ memory_xfer_auxv (struct target_ops *ops, if (current_inferior ()->attach_flag != 0) { - LONGEST retval; + enum target_xfer_status ret; - retval = ld_so_xfer_auxv (readbuf, writebuf, offset, len); - if (retval != -1) - return retval; + 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); + return procfs_xfer_auxv (readbuf, writebuf, offset, len, xfered_len); } /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR. Return 0 if *READPTR is already at the end of the buffer. Return -1 if there is insufficient buffer for a whole entry. Return 1 if an entry was read into *TYPEP and *VALP. */ -static int +int default_auxv_parse (struct target_ops *ops, gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp) { @@ -268,13 +286,13 @@ int target_auxv_parse (struct target_ops *ops, gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp) { - struct target_ops *t; + struct gdbarch *gdbarch = target_gdbarch(); + + if (gdbarch_auxv_parse_p (gdbarch)) + return gdbarch_auxv_parse (gdbarch, readptr, endptr, typep, valp); - for (t = ops; t != NULL; t = t->beneath) - if (t->to_auxv_parse != NULL) - return t->to_auxv_parse (t, readptr, endptr, typep, valp); - - return default_auxv_parse (ops, readptr, endptr, typep, valp); + return current_target.to_auxv_parse (¤t_target, readptr, endptr, + typep, valp); } @@ -340,7 +358,7 @@ get_auxv_inferior_data (struct target_ops *ops) info = inferior_data (inf, auxv_inferior_data); if (info == NULL) { - info = XZALLOC (struct auxv_info); + 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); @@ -441,6 +459,7 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops) 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);