.text .globl init_profiler .globl profile_r .globl profile_l .globl profile_l2 .globl profile_n .globl profile_n2 .globl profile_s .globl profile_s2 .globl profile_t .globl write_profile_stack .globl stack_trace_depth .if ! LINUX .globl allocate_memory .endif .globl __STRING__ .globl _ab_stack_size .globl _ew_print_string .globl _ew_print_char .globl _ew_print_text /* .globl print_error */ /* .globl profile_stack_pointer */ next = 0 name_ = 8 FunctionProfile = 16 profile_t: sub qword ptr profile_stack_pointer[rip],8 ret profile_r: sub qword ptr profile_stack_pointer[rip],8 ret profile_l: push rbx mov rbx,qword ptr [rbp] test rbx,rbx je allocate_function_profile_record_l allocate_function_profile_record_lr: mov rbp,qword ptr profile_stack_pointer[rip] mov qword ptr [rbp],rbx add rbp,8 mov qword ptr profile_stack_pointer[rip],rbp pop rbx ret allocate_function_profile_record_l: call allocate_function_profile_record att_jmp allocate_function_profile_record_lr profile_l2: push rbx mov rbx,qword ptr [rbp] test rbx,rbx je allocate_function_profile_record_l2 allocate_function_profile_record_l2r: mov rbp,qword ptr profile_stack_pointer[rip] mov qword ptr [rbp],rbx mov qword ptr 8[rbp],rbx add rbp,16 mov qword ptr profile_stack_pointer[rip],rbp pop rbx ret allocate_function_profile_record_l2: att_call allocate_function_profile_record att_jmp allocate_function_profile_record_l2r profile_n: push rbx mov rbx,qword ptr [rbp] test rbx,rbx je allocate_function_profile_record_n allocate_function_profile_record_nr: mov rbp,qword ptr profile_stack_pointer[rip] mov qword ptr [rbp],rbx add rbp,8 mov qword ptr profile_stack_pointer[rip],rbp pop rbx ret allocate_function_profile_record_n: att_call allocate_function_profile_record att_jmp allocate_function_profile_record_nr profile_n2: push rbx mov rbx,qword ptr [rbp] test rbx,rbx je allocate_function_profile_record_n2 allocate_function_profile_record_n2r: mov rbp,qword ptr profile_stack_pointer[rip] mov qword ptr [rbp],rbx mov qword ptr 8[rbp],rbx add rbp,16 mov qword ptr profile_stack_pointer[rip],rbp pop rbx ret allocate_function_profile_record_n2: att_call allocate_function_profile_record att_jmp allocate_function_profile_record_n2r profile_s2: push rbx mov rbx,qword ptr [rbp] test rbx,rbx je allocate_function_profile_record_s2 allocate_function_profile_record_s2r: mov rbp,qword ptr profile_stack_pointer[rip] mov qword ptr [rbp],rbx mov qword ptr 8[rbp],rbx add rbp,16 mov qword ptr profile_stack_pointer[rip],rbp pop rbx ret allocate_function_profile_record_s2: att_call allocate_function_profile_record att_jmp allocate_function_profile_record_s2r profile_s: push rbx mov rbx,qword ptr [rbp] test rbx,rbx je allocate_function_profile_record_s allocate_function_profile_record_sr: mov rbp,qword ptr profile_stack_pointer[rip] mov qword ptr [rbp],rbx add rbp,8 mov qword ptr profile_stack_pointer[rip],rbp pop rbx ret allocate_function_profile_record_s: att_call allocate_function_profile_record att_jmp allocate_function_profile_record_sr /* argument: rbp: function name adress-4 */ /* result: rbx: function profile record adress */ allocate_function_profile_record: push rax mov rax,qword ptr global_n_free_records_in_block[rip] mov rbx,qword ptr global_last_allocated_block[rip] test rax,rax jne no_alloc push rcx push rdx push rbp .if LINUX sub rsp,104 mov qword ptr [rsp],rsi mov qword ptr 8[rsp],rdi mov qword ptr 16[rsp],r8 mov qword ptr 24[rsp],r10 mov qword ptr 32[rsp],r11 movsd qword ptr 40[rsp],xmm0 movsd qword ptr 48[rsp],xmm1 movsd qword ptr 56[rsp],xmm2 movsd qword ptr 64[rsp],xmm3 movsd qword ptr 72[rsp],xmm4 movsd qword ptr 80[rsp],xmm5 movsd qword ptr 88[rsp],xmm6 movsd qword ptr 96[rsp],xmm7 .else sub rsp,72 mov qword ptr [rsp],r8 mov qword ptr 8[rsp],r10 mov qword ptr 16[rsp],r11 movsd qword ptr 24[rsp],xmm0 movsd qword ptr 32[rsp],xmm1 movsd qword ptr 40[rsp],xmm2 movsd qword ptr 48[rsp],xmm3 movsd qword ptr 56[rsp],xmm4 movsd qword ptr 64[rsp],xmm5 .endif mov rbp,rsp sub rsp,40 and rsp,-16 .if LINUX mov rdi,8192 /* 512*FunctionProfile */ att_call _malloc .else mov rcx,512*FunctionProfile call allocate_memory .endif mov rsp,rbp .if LINUX mov rsi,qword ptr [rsp] mov rdi,qword ptr 8[rsp] mov r8,qword ptr 16[rsp] mov r10,qword ptr 24[rsp] mov r11,qword ptr 32[rsp] movlpd xmm0,qword ptr 40[rsp] movlpd xmm1,qword ptr 48[rsp] movlpd xmm2,qword ptr 56[rsp] movlpd xmm3,qword ptr 64[rsp] movlpd xmm4,qword ptr 72[rsp] movlpd xmm5,qword ptr 80[rsp] movlpd xmm6,qword ptr 88[rsp] movlpd xmm7,qword ptr 96[rsp] add rsp,104 .else mov r8,qword ptr [rsp] mov r10,qword ptr 8[rsp] mov r11,qword ptr 16[rsp] movlpd xmm0,qword ptr 24[rsp] movlpd xmm1,qword ptr 32[rsp] movlpd xmm2,qword ptr 40[rsp] movlpd xmm3,qword ptr 48[rsp] movlpd xmm4,qword ptr 56[rsp] movlpd xmm5,qword ptr 64[rsp] add rsp,72 .endif test rax,rax pop rbp pop rdx pop rcx je no_memory mov rbx,rax mov rax,512 mov qword ptr global_last_allocated_block[rip],rbx no_alloc: dec rax mov qword ptr global_n_free_records_in_block[rip],rax lea rax,FunctionProfile[rbx] mov qword ptr global_last_allocated_block[rip],rax mov rax,qword ptr global_profile_records[rip] mov qword ptr name_[rbx],rbp mov qword ptr next[rbx],rax mov qword ptr global_profile_records[rip],rbx mov qword ptr [rbp],rbx pop rax ret no_memory: lea rbp,not_enough_memory_for_profiler[rip] pop rax att_jmp print_error write_profile_stack: .if LINUX mov r13,rsi mov r14,rdi .endif mov rax,qword ptr profile_stack_pointer[rip] test rax,rax je stack_not_initialised push rax mov rbp,rsp sub rsp,40 and rsp,-16 .if LINUX lea rdi,stack_trace_string[rip] .else lea rcx,stack_trace_string .endif att_call _ew_print_string mov rsp,rbp pop rax /* mov rbp,12 */ mov rbp,qword ptr stack_trace_depth[rip] write_functions_on_stack: mov rbx,qword ptr (-8)[rax] sub rax,8 test rbx,rbx je end_profile_stack push rax mov rcx,qword ptr name_[rbx] push rbp .if LINUX movsx rdx,dword ptr (-4)[rcx] lea rdx,-4[rcx+rdx] lea rdi,8[rcx] mov r12,rdx .else mov edx,dword ptr (-4)[rcx] add rcx,8 mov r12d,dword ptr [rdx] lea r13,4[rdx] .endif mov rbp,rsp sub rsp,40 and rsp,-16 att_call _ew_print_string .if LINUX lea rdi,module_string[rip] .else lea rcx,module_string .endif att_call _ew_print_string .if LINUX mov esi,dword ptr [r12] lea rdi,4[r12] .else mov rdx,r12 mov rcx,r13 .endif att_call _ew_print_text .if LINUX mov rdi,'] .else mov rcx,'] .endif att_call _ew_print_char .if LINUX mov rdi,10 .else mov rcx,10 .endif att_call _ew_print_char mov rsp,rbp pop rbp pop rax sub rbp,1 att_jne write_functions_on_stack end_profile_stack: stack_not_initialised: .if LINUX mov rsi,r13 mov rdi,r14 .endif ret init_profiler: mov rbp,rsp sub rsp,40 and rsp,-16 .if LINUX mov r13,rsi mov r14,rdi mov rdi,qword ptr _ab_stack_size[rip] att_call _malloc mov rsi,r13 mov rdi,r14 .else mov rcx,qword ptr ab_stack_size call allocate_memory .endif mov rsp,rbp test rax,rax je init_profiler_error push rax lea rbp,start_string[rip] att_call allocate_function_profile_record pop rdx mov qword ptr 8[rdx],rbx mov qword ptr [rdx],0 add rdx,16 mov qword ptr profile_stack_pointer[rip],rdx ret init_profiler_error: mov qword ptr profile_stack_pointer[rip],0 lea rbp,not_enough_memory_for_profile_stack[rip] att_jmp print_error .data .align 8 global_n_free_records_in_block: .quad 0 /* 0 n free records in block */ global_last_allocated_block: .quad 0 /* 8 latest allocated block */ global_profile_records: .quad 0 /* 16 profile record list */ stack_trace_depth: .quad 12 .align 8 /* m_system also defined in istartup.s */ /* m_system: .quad 6 .ascii "System" .byte 0 .byte 0 */ .long m_system-. start_string: .quad 0 .ascii "start" .byte 0 .align 8 not_enough_memory_for_profile_stack: .ascii "not enough memory for profile stack" .byte 10 .byte 0 not_enough_memory_for_profiler: .ascii "not enough memory for profiler" .byte 10 .byte 0 stack_trace_string: .ascii "Stack trace:" .byte 10 .byte 0 module_string: .ascii " [module: " .byte 0 .align 8 /* end */