aboutsummaryrefslogtreecommitdiff
path: root/gdb/solib-svr4.c
diff options
context:
space:
mode:
authorAleksandar Ristovski <aristovski@qnx.com>2011-10-18 14:00:42 +0000
committerAleksandar Ristovski <aristovski@qnx.com>2011-10-18 14:00:42 +0000
commit4313697959ffcaf3bf59556ef690914d0d7b84c3 (patch)
tree05e96c58735795e00e46f434bbba79056646090c /gdb/solib-svr4.c
parent9b0f109b0a400247d9c001cb815572e03cedb7f0 (diff)
downloadgdb-4313697959ffcaf3bf59556ef690914d0d7b84c3.zip
gdb-4313697959ffcaf3bf59556ef690914d0d7b84c3.tar.gz
gdb-4313697959ffcaf3bf59556ef690914d0d7b84c3.tar.bz2
* solib-svr4.c (read_program_header): New variables pt_phdr, pt_phdr_p,
initialize them from target PT_PHDR p_vaddr, relocate sect_addr by pt_phdr if PT_PHDR was found. * gdb.base/attach-pie-noexec.c: New files. * gdb.base/attach-pie-noexec.exp: New files.
Diffstat (limited to 'gdb/solib-svr4.c')
-rw-r--r--gdb/solib-svr4.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 2bb31a9..85bf27e 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -364,10 +364,11 @@ static gdb_byte *
read_program_header (int type, int *p_sect_size, int *p_arch_size)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
- CORE_ADDR at_phdr, at_phent, at_phnum;
+ CORE_ADDR at_phdr, at_phent, at_phnum, pt_phdr = 0;
int arch_size, sect_size;
CORE_ADDR sect_addr;
gdb_byte *buf;
+ int pt_phdr_p = 0;
/* Get required auxv elements from target. */
if (target_auxv_search (&current_target, AT_PHDR, &at_phdr) <= 0)
@@ -401,12 +402,23 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size)
/* Search for requested PHDR. */
for (i = 0; i < at_phnum; i++)
{
+ int p_type;
+
if (target_read_memory (at_phdr + i * sizeof (phdr),
(gdb_byte *)&phdr, sizeof (phdr)))
return 0;
- if (extract_unsigned_integer ((gdb_byte *)phdr.p_type,
- 4, byte_order) == type)
+ p_type = extract_unsigned_integer ((gdb_byte *) phdr.p_type,
+ 4, byte_order);
+
+ if (p_type == PT_PHDR)
+ {
+ pt_phdr_p = 1;
+ pt_phdr = extract_unsigned_integer ((gdb_byte *) phdr.p_vaddr,
+ 4, byte_order);
+ }
+
+ if (p_type == type)
break;
}
@@ -427,12 +439,23 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size)
/* Search for requested PHDR. */
for (i = 0; i < at_phnum; i++)
{
+ int p_type;
+
if (target_read_memory (at_phdr + i * sizeof (phdr),
(gdb_byte *)&phdr, sizeof (phdr)))
return 0;
- if (extract_unsigned_integer ((gdb_byte *)phdr.p_type,
- 4, byte_order) == type)
+ p_type = extract_unsigned_integer ((gdb_byte *) phdr.p_type,
+ 4, byte_order);
+
+ if (p_type == PT_PHDR)
+ {
+ pt_phdr_p = 1;
+ pt_phdr = extract_unsigned_integer ((gdb_byte *) phdr.p_vaddr,
+ 8, byte_order);
+ }
+
+ if (p_type == type)
break;
}
@@ -446,6 +469,16 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size)
8, byte_order);
}
+ /* PT_PHDR is optional, but we really need it
+ for PIE to make this work in general. */
+
+ if (pt_phdr_p)
+ {
+ /* at_phdr is real address in memory. pt_phdr is what pheader says it is.
+ Relocation offset is the difference between the two. */
+ sect_addr = sect_addr + (at_phdr - pt_phdr);
+ }
+
/* Read in requested program header. */
buf = xmalloc (sect_size);
if (target_read_memory (sect_addr, buf, sect_size))