x32 Fast tracepoints: Customize jump pad address
MAP_32BIT is ignored on x32, meaning the jump pad can end up somewhere between 2GB and 4GB, too far away from the executable for 5-byte relative jumps (JMP rel32). So on x32, try explicitly placing the jump pad near the middle of the available address space. gdb/gdbserver/ChangeLog: 2016-08-19 Pedro Alves <palves@redhat.com> * linux-amd64-ipa.c (alloc_jump_pad_buffer) [__ILP32__]: Try allocating around 0x80000000.
This commit is contained in:
parent
201506dadd
commit
9c235a72a1
2 changed files with 53 additions and 4 deletions
|
@ -1,3 +1,8 @@
|
|||
2016-08-19 Pedro Alves <palves@redhat.com>
|
||||
|
||||
* linux-amd64-ipa.c (alloc_jump_pad_buffer) [__ILP32__]: Try
|
||||
allocating around 0x80000000.
|
||||
|
||||
2016-08-19 Pedro Alves <palves@redhat.com>
|
||||
|
||||
PR gdb/20415
|
||||
|
|
|
@ -206,14 +206,57 @@ get_ipa_tdesc (int idx)
|
|||
"unknown ipa tdesc index: %d", idx);
|
||||
}
|
||||
|
||||
/* Allocate buffer for the jump pads. Since we're using 32-bit jumps
|
||||
to reach them, and the executable is at low addresses, MAP_32BIT
|
||||
works just fine. Shared libraries, being allocated at the top,
|
||||
are unfortunately out of luck. */
|
||||
/* Allocate buffer for the jump pads. The branch instruction has a
|
||||
reach of +/- 31-bit, and the executable is loaded at low addresses.
|
||||
|
||||
64-bit: Use MAP_32BIT to allocate in the first 2GB. Shared
|
||||
libraries, being allocated at the top, are unfortunately out of
|
||||
luck.
|
||||
|
||||
x32: Since MAP_32BIT is 64-bit only, do the placement manually.
|
||||
Try allocating at '0x80000000 - SIZE' initially, decreasing until
|
||||
we hit a free area. This ensures the executable is fully covered,
|
||||
and is as close as possible to the shared libraries, which are
|
||||
usually mapped at the top of the first 4GB of the address space.
|
||||
*/
|
||||
|
||||
void *
|
||||
alloc_jump_pad_buffer (size_t size)
|
||||
{
|
||||
#if __ILP32__
|
||||
uintptr_t addr;
|
||||
int pagesize;
|
||||
|
||||
pagesize = sysconf (_SC_PAGE_SIZE);
|
||||
if (pagesize == -1)
|
||||
perror_with_name ("sysconf");
|
||||
|
||||
addr = 0x80000000 - size;
|
||||
|
||||
/* size should already be page-aligned, but this can't hurt. */
|
||||
addr &= ~(pagesize - 1);
|
||||
|
||||
/* Search for a free area. If we hit 0, we're out of luck. */
|
||||
for (; addr; addr -= pagesize)
|
||||
{
|
||||
void *res;
|
||||
|
||||
/* No MAP_FIXED - we don't want to zap someone's mapping. */
|
||||
res = mmap ((void *) addr, size,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
/* If we got what we wanted, return. */
|
||||
if ((uintptr_t) res == addr)
|
||||
return res;
|
||||
|
||||
/* If we got a mapping, but at a wrong address, undo it. */
|
||||
if (res != MAP_FAILED)
|
||||
munmap (res, size);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
void *res = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
|
||||
|
||||
|
@ -221,6 +264,7 @@ alloc_jump_pad_buffer (size_t size)
|
|||
return NULL;
|
||||
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue