The following function:
void cpystring(char *to, char const *from)
{
while ( *to++ = *from++ );
}
gets compiled on a x86_64 Linux machine to:
00000000000005ca <_Z9cpystringPcPKc>:
5ca: 55 push %rbp
5cb: 48 89 e5 mov %rsp,%rbp
5ce: 48 89 7d f8 mov %rdi,-0x8(%rbp)
5d2: 48 89 75 f0 mov %rsi,-0x10(%rbp)
5d6: 48 8b 55 f0 mov -0x10(%rbp),%rdx
5da: 48 8d 42 01 lea 0x1(%rdx),%rax
5de: 48 89 45 f0 mov %rax,-0x10(%rbp)
5e2: 48 8b 45 f8 mov -0x8(%rbp),%rax
5e6: 48 8d 48 01 lea 0x1(%rax),%rcx
5ea: 48 89 4d f8 mov %rcx,-0x8(%rbp)
5ee: 0f b6 12 movzbl (%rdx),%edx
5f1: 88 10 mov %dl,(%rax)
5f3: 0f b6 00 movzbl (%rax),%eax
5f6: 84 c0 test %al,%al
5f8: 0f 95 c0 setne %al
5fb: 84 c0 test %al,%al
5fd: 74 02 je 601 <_Z9cpystringPcPKc+0x37>
5ff: eb d5 jmp 5d6 <_Z9cpystringPcPKc+0xc>
601: 90 nop
602: 5d pop %rbp
603: c3 retq
And so here's the first program that allocates the interprocess memory and copies the machine code into it:
char unsigned const g_cpystring_bytes[] = {
0x55, 0x48, 0x89, 0xE5, 0x48, 0x89, 0x7D, 0xF8, 0x48, 0x89, 0x75, 0xF0, 0x48, 0x8B, 0x55, 0xF0,
0x48, 0x8D, 0x42, 0x01, 0x48, 0x89, 0x45, 0xF0, 0x48, 0x8B, 0x45, 0xF8, 0x48, 0x8D, 0x48, 0x01,
0x48, 0x89, 0x4D, 0xF8, 0x0F, 0xB6, 0x12, 0x88, 0x10, 0x0F, 0xB6, 0x00, 0x84, 0xC0, 0x0F, 0x95,
0xC0, 0x84, 0xC0, 0x74, 0x02, 0xEB, 0xD5, 0x90, 0x5D, 0xC3
};
#include <cstring> // memcpy
#include <boost/interprocess/shared_memory_object.hpp> // shared_memory_object
#include <boost/interprocess/mapped_region.hpp> // mapped_region
using namespace boost::interprocess;
int main(void)
{
shared_memory_object shm_obj(create_only, //only create
"gotham_cpystring", //name
read_write ); //read-write mode
shm_obj.truncate(sizeof g_cpystring_bytes);
mapped_region region(shm_obj, read_write);
std::memcpy(region.get_address(), g_cpystring_bytes, region.get_size());
}
This first program compiles fine and seems to do its job properly, the shared memory object is created in "/dev/shm" and it's 58 bytes in size.
And then next I have the second program that tries to call the function:
#include <boost/interprocess/shared_memory_object.hpp> // shared_memory_object
#include <boost/interprocess/mapped_region.hpp> // mapped_region
using namespace boost::interprocess;
char buf1[] = "cat",
buf2[] = "dog";
//Not sure if I need to specify the calling convention (e.g. sysv_abi)
void (*cpystring)(char *to, char const *from) = nullptr;
int main(void)
{
//Open already created shared memory object.
shared_memory_object shm_obj(open_only, "gotham_cpystring", read_write);
//Map the whole shared memory in this process
mapped_region region(shm_obj, read_write);
cpystring = reinterpret_cast<decltype(cpystring)>(region.get_address());
cpystring(buf1, buf2);
}
This second program fails with a segfault. I thought the problem might be that the shared memory is in a page that isn't marked for execution, and so I set it as executable as follows:
void Set_Writeability_Of_Memory(void *const p, bool const writeable)
{
uintptr_t const page_size = sysconf(_SC_PAGE_SIZE);
union {
void *p_start_of_page;
uintptr_t i_start_of_page;
};
p_start_of_page = p;
i_start_of_page -= (i_start_of_page % page_size);
mprotect(i_start_of_page, page_size, PROT_READ | (writeable ? PROT_WRITE : 0u));
}
however this hasn't fixed it. I call the function "Set_Writeability_Of_Memory" from within my first program and also from within my second program, but the second program still segfaults.
Anyone got any ideas?
Here's what I'm getting from the GDB debugger:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7ff7000 in ?? ()
(gdb) bt
#0 0x00007ffff7ff7000 in ?? ()
#1 0x0000555555555366 in main () at drone.cpp:26