pow() fails with a segmentation fault when executed from dynamically allocated memory

Ángel González keisial@gmail.com
Sat Jan 28 14:37:00 GMT 2012


On 28/01/12 13:21, Carlos O'Donell wrote:
> IIUC you have a code trampoline in dynamically allocated memory
> which calls my_pow() and somtimes it segfaults?
>
> Rather than making me decode the trampoline by hand, could you
> please provide the assembly instructions for the trampoline?
>
> Is there any reason you wrote the trampoline out by hand?
>
> My preference would have been to write the trampoline in C,
> let the compiler compile it, dynamically allocate the memory,
> and then memcpy the trampoline into place. The alternative
> being: compile the trampoline from an assembly file which has
> two symbols that mark the start and the end of the trampoline.
> In either case you get the benefit of the assembler which will
> double check your encoding and warn you if you made a mistake.
> If you use a C compiler it's even better because you then are
> assured you didn't make a procedure-call error.
>
> Cheers,
> Carlos.
I get the same failing behavior in both testcases as the reporter.

I have rewritten the testcase with a struct + memcpy (see below).

This way it can be disassembled with objdump -D, which shows
> 0000000000600b50 <value>:
>   600b50:    49 bb c0 06 40 00 00     movabs $0x4006c0,%r11
>   600b57:    00 00 00
>   600b5a:    41 ff d3                 callq  *%r11
>   600b5d:    c3                       retq
>     ...
0x4006c0 is the address asignated to my_pow. Disassembled below:
> 00000000004006c0 <my_pow>:
>   4006c0:    48 83 ec 18                  sub    $0x18,%rsp
>   4006c4:    bf ec 07 40 00              mov    $0x4007ec,%edi
>   4006c9:    e8 22 fe ff ff                  callq  4004f0 <puts@plt>
>   4006ce:    f2 0f 10 0d 42 01 00     movsd  0x142(%rip),%xmm1        
> # 400818 <_IO_stdin_used+0x30>
>   4006d5:    00
>   4006d6:    f2 0f 10 05 42 01 00     movsd  0x142(%rip),%xmm0        
> # 400820 <_IO_stdin_used+0x38>
>   4006dd:    00
>   4006de:    e8 3d fe ff ff                   callq  400520 <pow@plt>
>   4006e3:    bf f1 07 40 00               mov    $0x4007f1,%edi
>   4006e8:    f2 0f 11 04 24               movsd  %xmm0,(%rsp)
>   4006ed:    e8 fe fd ff ff                   callq  4004f0 <puts@plt>
>   4006f2:    f2 0f 10 04 24                movsd  (%rsp),%xmm0
>   4006f7:    48 83 c4 18                   add    $0x18,%rsp
>   4006fb:    c3                                  retq




#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <sys/mman.h>

volatile double my_pow() {
   printf("test\n");
   double ret = pow(-2.0, 0.5);
   printf("test2\n");
   return ret;
}

struct {
   char a, b;
   void *addr;
   char c, d, e, f;
} __attribute__((packed)) value = { 0x49, 0xBB, &my_pow, 0x41, 0xff, 
0xd3, 0xc3 };

void execute() {

   uint8_t *code = ( uint8_t * ) mmap( NULL, 1024,
     PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 
0 );

   memcpy(code, &value, sizeof(value));

   double (*fun)(void) = (double (*)(void))code;
   printf("value is at %p\n", &value);

   printf("Result: %f\n", my_pow());
   printf("Result: %f\n", fun());
}

int main() {
   execute();
   return 0;
}



More information about the Libc-help mailing list