#if defined(lint)
#include <sys/types.h>
#include "_rtld.h"
#include "_audit.h"
#include "_elf.h"
int
elf_plt_trace()
{
return (0);
}
#else
#include <link.h>
#include "_audit.h"
.file "boot_elf.s"
.text
#define REFLMP_OFF 0x0
#define DEFLMP_OFF 0x4
#define SYMNDX_OFF 0x8
#define SBFLAGS_OFF 0xc
#define SYMDEF_OFF 0x10
#define SYMDEF_VALUE_OFF 0x14
.globl elf_plt_trace
.type elf_plt_trace,@function
.align 16
elf_plt_trace:
subl $84,%esp / create some local storage
pushl %eax
pushl %ebx
pushl %edi
pushl %esi
call .L1 / initialize %ebx to GOT
.L1:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L1], %ebx
movl -4(%ebp), %eax / %eax = dyndata
testb $LA_SYMB_NOPLTENTER, 0xc(%eax) / <link.h>
je .start_pltenter
movl SYMDEF_VALUE_OFF(%eax), %edi
movl %edi, -8(%ebp) / save destination address
jmp .end_pltenter
.start_pltenter:
lea 4(%ebp), %edi
movl %edi, -84(%ebp) / %esp
movl 0(%ebp), %edi
movl %edi, -80(%ebp) / %ebp
movl -4(%ebp), %edi
lea SBFLAGS_OFF(%edi), %eax
pushl %eax / arg5 (&sb_flags)
lea -84(%ebp), %eax
pushl %eax / arg4 (regset)
pushl SYMNDX_OFF(%edi) / arg3 (symndx)
lea SYMDEF_OFF(%edi), %eax
pushl %eax / arg2 (&sym)
pushl DEFLMP_OFF(%edi) / arg1 (dlmp)
pushl REFLMP_OFF(%edi) / arg0 (rlmp)
call audit_pltenter@PLT
addl $24, %esp / cleanup stack
movl %eax, -8(%ebp) / save calling address
.end_pltenter:
movl audit_flags@GOT(%ebx), %eax
movl (%eax), %eax
andl $AF_PLTEXIT, %eax / value of audit.h:AF_PLTEXIT
cmpl $0, %eax
je .bypass_pltexit
testb $LA_SYMB_NOPLTEXIT, 12(%edi)
je .start_pltexit
.bypass_pltexit:
movl 0(%ebp), %eax
movl %eax, -4(%ebp)
movl -8(%ebp), %eax / eax == calling destination
movl %eax, 0(%ebp) / store destination at top
popl %esi /
popl %edi / clean up stack
popl %ebx /
popl %eax /
subl $4, %ebp / adjust %ebp for 'ret'
movl %ebp, %esp /
popl %ebp /
ret / jmp to final destination
/ and clean up stack :)
.start_pltexit:
movl %ebp, %edi /
addl $8, %edi / %edi = src
movl (%ebp), %edx /
subl %edi, %edx / %edx == prev frame sz
movl audit_argcnt@GOT(%ebx),%eax
movl (%eax), %eax / %eax = audit_argcnt
cmpl $0, %eax
jle .grow_stack
lea (,%eax,4), %eax / %eax = %eax * 4
cmpl %eax,%edx
jle .grow_stack
movl %eax, %edx
.grow_stack:
subl %edx, %esp / grow the stack
movl %edx, -88(%ebp) / -88(%ebp) == prev frame sz
movl %esp, %ecx / %ecx = dest
addl %ecx, %edx / %edx == tail of dest
.while_base:
cmpl %edx, %ecx / while (base+size >= src++) {
jge .end_while /
movl (%edi), %esi
movl %esi,(%ecx) / *dest = *src
addl $4, %edi / src++
addl $4, %ecx / dest++
jmp .while_base / }
.end_while:
movl -92(%ebp), %eax / restore %eax
movl -96(%ebp), %ebx / restore %ebx
movl -104(%ebp), %esi / restore %esi
movl -8(%ebp), %edi
call *%edi / call dest_proc()
addl -88(%ebp), %esp / cleanup dupped stack
movl -4(%ebp), %edi
pushl SYMNDX_OFF(%edi) / arg4 (symndx)
lea SYMDEF_OFF(%edi), %ecx
pushl %ecx / arg3 (symp)
pushl DEFLMP_OFF(%edi) / arg2 (dlmp)
pushl REFLMP_OFF(%edi) / arg1 (rlmp)
pushl %eax / arg0 (retval)
call audit_pltexit@PLT
addl $20, %esp / cleanup stack
popl %esi /
popl %edi / clean up stack
popl %ebx /
movl %ebp, %esp /
popl %ebp /
ret / return to caller
.size elf_plt_trace, .-elf_plt_trace
#endif
#if defined(lint)
extern unsigned long elf_bndr(Rt_map *, unsigned long, caddr_t);
void
elf_rtbndr(Rt_map * lmp, unsigned long reloc, caddr_t pc)
{
(void) elf_bndr(lmp, reloc, pc);
}
#else
.globl elf_bndr
.globl elf_rtbndr
.weak _elf_rtbndr
_elf_rtbndr = elf_rtbndr / Make dbx happy
.type elf_rtbndr,@function
.align 4
elf_rtbndr:
pushl %ebp
movl %esp, %ebp
pushl %eax
pushl %ecx
pushl %edx
pushl 12(%ebp) / push pc
pushl 8(%ebp) / push reloc
pushl 4(%ebp) / push *lmp
call elf_bndr@PLT / call the C binder code
addl $12, %esp / pop args
movl %eax, 8(%ebp) / store final destination
popl %edx
popl %ecx
popl %eax
movl %ebp, %esp
popl %ebp
addl $4,%esp / pop args
ret / invoke resolved function
.size elf_rtbndr, .-elf_rtbndr
#endif