[nto] Implement TARGET_OBJECT_AUXV.
Fix 'info auxv' for nto. gdb/ChangeLog: * nto-procfs.c (sys/auxv.h): Include. (procfs_xfer_partial): Implement TARGET_OBJECT_AUXV. * nto-tdep.c (nto_read_auxv_from_initial_stack): New function. * nto-tdep.h (nto_read_auxv_from_initial_stack): New declaration.
This commit is contained in:
parent
609c3040c2
commit
8a6c0ccdd2
@ -1,3 +1,10 @@
|
||||
2015-10-20 Aleksandar Ristovski <aristovski@qnx.com>
|
||||
|
||||
* nto-procfs.c (sys/auxv.h): Include.
|
||||
(procfs_xfer_partial): Implement TARGET_OBJECT_AUXV.
|
||||
* nto-tdep.c (nto_read_auxv_from_initial_stack): New function.
|
||||
* nto-tdep.h (nto_read_auxv_from_initial_stack): New declaration.
|
||||
|
||||
2015-10-20 Aleksandar Ristovski <aristovski@qnx.com>
|
||||
|
||||
* nto-procfs.c (nto_procfs_path): Rename to...
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <sys/syspage.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/netmgr.h>
|
||||
#include <sys/auxv.h>
|
||||
|
||||
#include "gdbcore.h"
|
||||
#include "inferior.h"
|
||||
#include "target.h"
|
||||
@ -885,6 +887,38 @@ procfs_xfer_partial (struct target_ops *ops, enum target_object object,
|
||||
{
|
||||
case TARGET_OBJECT_MEMORY:
|
||||
return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
|
||||
case TARGET_OBJECT_AUXV:
|
||||
if (readbuf != NULL)
|
||||
{
|
||||
int err;
|
||||
CORE_ADDR initial_stack;
|
||||
debug_process_t procinfo;
|
||||
/* For 32-bit architecture, size of auxv_t is 8 bytes. */
|
||||
const unsigned int sizeof_auxv_t = sizeof (auxv_t);
|
||||
const unsigned int sizeof_tempbuf = 20 * sizeof_auxv_t;
|
||||
int tempread;
|
||||
gdb_byte *const tempbuf = alloca (sizeof_tempbuf);
|
||||
|
||||
if (tempbuf == NULL)
|
||||
return TARGET_XFER_E_IO;
|
||||
|
||||
err = devctl (ctl_fd, DCMD_PROC_INFO, &procinfo,
|
||||
sizeof procinfo, 0);
|
||||
if (err != EOK)
|
||||
return TARGET_XFER_E_IO;
|
||||
|
||||
initial_stack = procinfo.initial_stack;
|
||||
|
||||
/* procfs is always 'self-hosted', no byte-order manipulation. */
|
||||
tempread = nto_read_auxv_from_initial_stack (initial_stack, tempbuf,
|
||||
sizeof_tempbuf,
|
||||
sizeof (auxv_t));
|
||||
tempread = min (tempread, len) - offset;
|
||||
memcpy (readbuf, tempbuf + offset, tempread);
|
||||
*xfered_len = tempread;
|
||||
return tempread ? TARGET_XFER_OK : TARGET_XFER_EOF;
|
||||
}
|
||||
/* Fallthru */
|
||||
default:
|
||||
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
|
||||
readbuf, writebuf, offset, len,
|
||||
|
@ -394,3 +394,86 @@ nto_initialize_signals (void)
|
||||
signal_pass_update (SIGPHOTON, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Read AUXV from initial_stack. */
|
||||
LONGEST
|
||||
nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack, gdb_byte *readbuf,
|
||||
LONGEST len, size_t sizeof_auxv_t)
|
||||
{
|
||||
gdb_byte targ32[4]; /* For 32 bit target values. */
|
||||
gdb_byte targ64[8]; /* For 64 bit target values. */
|
||||
CORE_ADDR data_ofs = 0;
|
||||
ULONGEST anint;
|
||||
LONGEST len_read = 0;
|
||||
gdb_byte *buff;
|
||||
enum bfd_endian byte_order;
|
||||
int ptr_size;
|
||||
|
||||
if (sizeof_auxv_t == 16)
|
||||
ptr_size = 8;
|
||||
else
|
||||
ptr_size = 4;
|
||||
|
||||
/* Skip over argc, argv and envp... Comment from ldd.c:
|
||||
|
||||
The startup frame is set-up so that we have:
|
||||
auxv
|
||||
NULL
|
||||
...
|
||||
envp2
|
||||
envp1 <----- void *frame + (argc + 2) * sizeof(char *)
|
||||
NULL
|
||||
...
|
||||
argv2
|
||||
argv1
|
||||
argc <------ void * frame
|
||||
|
||||
On entry to ldd, frame gives the address of argc on the stack. */
|
||||
/* Read argc. 4 bytes on both 64 and 32 bit arches and luckily little
|
||||
* endian. So we just read first 4 bytes. */
|
||||
if (target_read_memory (initial_stack + data_ofs, targ32, 4) != 0)
|
||||
return 0;
|
||||
|
||||
byte_order = gdbarch_byte_order (target_gdbarch ());
|
||||
|
||||
anint = extract_unsigned_integer (targ32, sizeof (targ32), byte_order);
|
||||
|
||||
/* Size of pointer is assumed to be 4 bytes (32 bit arch.) */
|
||||
data_ofs += (anint + 2) * ptr_size; /* + 2 comes from argc itself and
|
||||
NULL terminating pointer in
|
||||
argv. */
|
||||
|
||||
/* Now loop over env table: */
|
||||
anint = 0;
|
||||
while (target_read_memory (initial_stack + data_ofs, targ64, ptr_size)
|
||||
== 0)
|
||||
{
|
||||
if (extract_unsigned_integer (targ64, ptr_size, byte_order) == 0)
|
||||
anint = 1; /* Keep looping until non-null entry is found. */
|
||||
else if (anint)
|
||||
break;
|
||||
data_ofs += ptr_size;
|
||||
}
|
||||
initial_stack += data_ofs;
|
||||
|
||||
memset (readbuf, 0, len);
|
||||
buff = readbuf;
|
||||
while (len_read <= len-sizeof_auxv_t)
|
||||
{
|
||||
if (target_read_memory (initial_stack + len_read, buff, sizeof_auxv_t)
|
||||
== 0)
|
||||
{
|
||||
/* Both 32 and 64 bit structures have int as the first field. */
|
||||
const ULONGEST a_type
|
||||
= extract_unsigned_integer (buff, sizeof (targ32), byte_order);
|
||||
|
||||
if (a_type == AT_NULL)
|
||||
break;
|
||||
buff += sizeof_auxv_t;
|
||||
len_read += sizeof_auxv_t;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return len_read;
|
||||
}
|
||||
|
@ -168,4 +168,7 @@ int nto_in_dynsym_resolve_code (CORE_ADDR pc);
|
||||
|
||||
char *nto_extra_thread_info (struct target_ops *self, struct thread_info *);
|
||||
|
||||
LONGEST nto_read_auxv_from_initial_stack (CORE_ADDR inital_stack,
|
||||
gdb_byte *readbuf,
|
||||
LONGEST len, size_t sizeof_auxv_t);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user