Skip to content

Instantly share code, notes, and snippets.

@eatnumber1
Created October 11, 2011 13:17
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eatnumber1/1278047 to your computer and use it in GitHub Desktop.
Save eatnumber1/1278047 to your computer and use it in GitHub Desktop.
Dynamic linking example
A hand-crafted dynamic resolver.
*.o
.*.swp
.*.swo
resolver
.globl _trampoline
_trampoline:
# Be kind to debuggers, set up a stack frame.
pushl %ebp
movl %esp, %ebp
# Make space for the resolved ptr
subl $0x04, %esp
# Save EVERYTHING
pushl %eax
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
pushl %edi
# 16-Byte Align the stack
subl $0x0C, %esp
# Call the resolver and save the result
calll _resolver
movl %eax, -0x04(%ebp)
# Remove aligment padding
addl $0x0C, %esp
# Restore EVERYTHING
popl %edi
popl %esi
popl %edx
popl %ecx
popl %ebx
popl %eax
# Destroy stack frame
movl %ebp, %esp
popl %ebp
# Jump back to origin
jmpl *-0x8(%esp)
.globl _trampoline
_trampoline:
# Be kind to debuggers, set up a stack frame.
pushq %rbp
movq %rsp, %rbp
# Make space for the resolved ptr
subq $0x08, %rsp
# Save EVERYTHING
pushq %rax
pushq %rbx
pushq %rcx
pushq %rdx
pushq %rsi
pushq %rdi
pushq %r8
pushq %r9
pushq %r10
pushq %r11
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# 16-Byte Align the stack
subq $0x08, %rsp
# Call the resolver and save the result
callq _resolver
movq %rax, -0x08(%rbp)
# Remove aligment padding
addq $0x08, %rsp
# Restore EVERYTHING
popq %r15
popq %r14
popq %r13
popq %r12
popq %r11
popq %r10
popq %r9
popq %r8
popq %rdi
popq %rsi
popq %rdx
popq %rcx
popq %rbx
popq %rax
# Destroy stack frame
movq %rbp, %rsp
popq %rbp
# Jump back to origin
jmpq *-0x10(%rsp)
.globl _resolver
.globl trampoline
resolver_ptr:
.long resolver
_trampoline_ptr:
.long _trampoline
_resolver:
jmp *resolver_ptr
trampoline:
jmp *_trampoline_ptr
CC := clang
CFLAGS := -ggdb
ASFLAGS := $(CFLAGS)
CPPFLAGS := -Wall -Werror -Wextra
C_SOURCES := resolver.c
ASM_32_BIT := bind32.s
ASM_64_BIT := bind64.s
ARCH_BITS := $(shell getconf LONG_BIT)
PLATFORM := $(shell uname -s)
ifeq "$(PLATFORM)" "Linux"
ASM_32_BIT := $(ASM_32_BIT) linux_trampoline.s
ASM_64_BIT := $(ASM_64_BIT) linux_trampoline.s
endif
SOURCES := $(C_SOURCES)
ifeq "$(ARCH_BITS)" "32"
SOURCES := $(SOURCES) $(ASM_32_BIT)
else ifeq "$(ARCH_BITS)" "64"
SOURCES := $(SOURCES) $(ASM_64_BIT)
else
$(error Architecture not supported)
endif
OBJECTS := $(SOURCES:.c=.o)
OBJECTS := $(OBJECTS:.s=.o)
.PHONY: all clean
all: resolver
clean:
$(RM) $(OBJECTS) resolver
resolver: $(OBJECTS)
$(CC) $(LDFLAGS) -o $@ $^
%.o: %.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
%.o: %.s
$(CC) -c $(ASFLAGS) -o $@ $<
#include <stdio.h>
void trampoline( char * );
void (*fp)( char * ) = trampoline;
void resolved( char *s ) {
printf("%s\n", s);
}
void *resolver() {
printf("resolving fp... ");
fp = resolved;
printf("ok\n");
return fp;
}
int main() {
fp("Hello World!");
fp("Hello World!");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment