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:
Pedro Alves 2016-08-19 12:07:45 +01:00
parent 201506dadd
commit 9c235a72a1
2 changed files with 53 additions and 4 deletions

View file

@ -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

View file

@ -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