18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file op_syscalls.c 38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Tracing of system calls 48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2002 OProfile authors 68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING 78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Bob Montgomery 98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Will Cohen 108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author John Levon 118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie 128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <linux/sched.h> 158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <linux/unistd.h> 168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <linux/mman.h> 178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <linux/file.h> 188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "oprofile.h" 208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_dcache.h" 218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_util.h" 228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodduint dname_top; 248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct qstr **dname_stack; 258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddchar * pool_pos; 268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddchar * pool_start; 278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddchar * pool_end; 288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid oprof_put_note(struct op_note * samp); 308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* ------------ system calls --------------- */ 328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct mmap_arg_struct { 348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long addr; 358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long len; 368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long prot; 378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long flags; 388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long fd; 398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long offset; 408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}; 418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* --------- IA64 versions of system calls ------ */ 438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage static int (*old_sys_clone)(long, long); 448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage static int (*old_sys_clone2)(long, long, long); 458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage static int (*old_sys_execve)(char *, char **, char **); 468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage static unsigned long (*old_sys_mmap)(unsigned long, 478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long, int, int, int, long); 488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage static unsigned long (*old_sys_mmap2)(unsigned long, 498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long, int, int, int, long); 508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage static long (*old_sys_init_module)(char const *, struct module *); 518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage static long (*old_sys_exit)(int); 528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* --------- declarations of interception stubs for IA64 ------ */ 548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage long post_stub_clone(long, long); 558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage long post_stub_clone2(long, long, long); 568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage long my_ia64_execve(char *, char **, char **); 578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage unsigned long post_stub_mmap(unsigned long, 588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long, int, int, int, long); 598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage unsigned long post_stub_mmap2(unsigned long, 608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unsigned long, int, int, int, long); 618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage long post_stub_init_module(char const *, struct module *); 628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage long pre_stub_exit(int); 638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* IA64 system call table doesn't use function pointers, it uses 658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * pointers to code (not the same thing). Basically it can violate the 668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * procedure calling rules because these "procedure calls" are made by 678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * the assembly language BREAK handler in ivt.S. 688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct fdesc { 718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd void * ip; 728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd void * gp; 738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}; 748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct fdesc fdesc_clone; 768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct fdesc fdesc_clone2; 778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct fdesc fdesc_execve; 788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct fdesc fdesc_mmap; 798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct fdesc fdesc_mmap2; 808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct fdesc fdesc_init_module; 818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct fdesc fdesc_exit; 828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* ----------- End of IA64 weirdness for now -------------- */ 838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddspinlock_t map_lock = SPIN_LOCK_UNLOCKED; 858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* called with map_lock held */ 878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void oprof_output_map(ulong addr, ulong len, 888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ulong offset, struct file * file, int is_execve) 898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd struct op_note note; 918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* don't bother with /dev/zero mappings etc. */ 938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!len) 948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.pid = current->pid; 978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.tgid = op_get_tgid(); 988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.addr = addr; 998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.len = len; 1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.offset = offset; 1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.type = is_execve ? OP_EXEC : OP_MAP; 1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.hash = hash_path(file); 1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (note.hash == -1) 1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_put_note(¬e); 1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int oprof_output_maps(struct task_struct * task) 1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd int size=0; 1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd struct mm_struct * mm; 1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd struct vm_area_struct * map; 1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* we don't need to worry about mm_users here, since there is at 1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd least one user (current), and if there's other code using this 1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd mm, then mm_users must be at least 2; we should never have to 1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd mmput() here. */ 1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!(mm = task->mm)) 1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd goto out; 1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd lock_mmap(mm); 1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spin_lock(&map_lock); 1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* We need two pass, daemon assume than the first mmap notification 1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * is for the executable but some process doesn't follow this model. 1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (map = mm->mmap; map; map = map->vm_next) { 1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!(map->vm_flags & VM_EXEC) || !map->vm_file) 1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd continue; 1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!(map->vm_flags & VM_EXECUTABLE)) 1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd continue; 1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_output_map(map->vm_start, map->vm_end-map->vm_start, 1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd GET_VM_OFFSET(map), map->vm_file, 1); 1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (map = mm->mmap; map; map = map->vm_next) { 1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!(map->vm_flags & VM_EXEC) || !map->vm_file) 1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd continue; 1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (map->vm_flags & VM_EXECUTABLE) 1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd continue; 1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_output_map(map->vm_start, map->vm_end-map->vm_start, 1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd GET_VM_OFFSET(map), map->vm_file, 0); 1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spin_unlock(&map_lock); 1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unlock_mmap(mm); 1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout: 1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return size; 1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* execve is a special case on IA64. The others get the result and 1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * arguments after the system call has been made from the ASM stub. */ 1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage long 1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddmy_sys_execve (char * filename, char **argv, char **envp, struct pt_regs * regs) 1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd int error; 1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_INC_USE_COUNT; 1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd filename = getname(filename); 1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd error = PTR_ERR(filename); 1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (IS_ERR(filename)) 1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd goto out; 1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd error = do_execve(filename, argv, envp, regs); 1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!error) { 1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd PTRACE_OFF(current); 1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_output_maps(current); 1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd putname(filename); 1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout: 1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unlock_execve(); 1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_DEC_USE_COUNT; 1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return error; 1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void out_mmap(ulong addr, ulong len, ulong prot, ulong flags, 1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ulong fd, ulong offset) 1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd struct file * file; 1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd lock_out_mmap(); 1888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd file = fget(fd); 1908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!file) 1918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd goto out; 1928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spin_lock(&map_lock); 1948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_output_map(addr, len, offset, file, 0); 1958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spin_unlock(&map_lock); 1968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fput(file); 1988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout: 2008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unlock_out_mmap(); 2018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* 2058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * IA64 mmap routines: 2068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * The post_sys_* routines are called after the syscall has been made. 2078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * The first argument is the return value from the system call. 2088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 2098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage void post_sys_mmap2(ulong ret, ulong addr, ulong len, 2108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ulong prot, ulong flags, ulong fd, ulong pgoff) 2118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* FIXME: This should be done in the ASM stub. */ 2138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_INC_USE_COUNT; 2148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if ((prot & PROT_EXEC) && ret >= 0) 2168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out_mmap(ret, len, prot, flags, fd, pgoff << PAGE_SHIFT); 2178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd goto out; 2188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout: 2198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_DEC_USE_COUNT; 2208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage void post_sys_mmap(ulong ret, ulong addr, ulong len, 2238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ulong prot, ulong flags, ulong fd, ulong off) 2248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* FIXME: This should be done in the ASM stub. */ 2268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_INC_USE_COUNT; 2278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if ((prot & PROT_EXEC) && ret >= 0) 2298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out_mmap(ret, len, prot, flags, fd, off); 2308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd goto out; 2318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout: 2328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_DEC_USE_COUNT; 2338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddinline static void oprof_report_fork(u32 old_pid, u32 new_pid, u32 old_tgid, u32 new_tgid) 2378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd struct op_note note; 2398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.type = OP_FORK; 2418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.pid = old_pid; 2428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.tgid = old_tgid; 2438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.addr = new_pid; 2448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.len = new_tgid; 2458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_put_note(¬e); 2468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage void post_sys_clone(long ret, long arg0, long arg1) 2508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 pid = current->pid; 2528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 tgid = op_get_tgid(); 2538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* FIXME: This should be done in the ASM stub. */ 2558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_INC_USE_COUNT; 2568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (ret) 2588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* FIXME: my libc show clone() is not implemented in ia64 2598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * but used only by fork() with a SIGCHILD first parameter 2608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * so we assume it's a fork */ 2618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_report_fork(pid, ret, pid, tgid); 2628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_DEC_USE_COUNT; 2638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage void post_sys_clone2(long ret, long arg0, long arg1, long arg2) 2668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 pid = current->pid; 2688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd u32 tgid = op_get_tgid(); 2698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd long clone_flags = arg0; 2708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* FIXME: This should be done in the ASM stub. */ 2728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_INC_USE_COUNT; 2738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (ret) { 2758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (clone_flags & CLONE_THREAD) 2768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_report_fork(pid, ret, tgid, tgid); 2778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 2788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_report_fork(pid, ret, tgid, ret); 2798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_DEC_USE_COUNT; 2818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage void 2848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddpost_sys_init_module(long ret, char const * name_user, 2858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd struct module * mod_user) 2868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* FIXME: This should be done in the ASM stub. */ 2888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_INC_USE_COUNT; 2898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (ret >= 0) { 2918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd struct op_note note; 2928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.type = OP_DROP_MODULES; 2948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_put_note(¬e); 2958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_DEC_USE_COUNT; 2978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* Exit must use a pre-call intercept stub. There is no post exit. */ 3008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasmlinkage void pre_sys_exit(int error_code) 3018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd struct op_note note; 3038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_INC_USE_COUNT; 3058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.addr = current->times.tms_utime; 3078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.len = current->times.tms_stime; 3088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.offset = current->start_time; 3098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.type = OP_EXIT; 3108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.pid = current->pid; 3118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note.tgid = op_get_tgid(); 3128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd oprof_put_note(¬e); 3138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* this looks UP-dangerous, as the exit sleeps and we don't 3158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * have a use count, but in fact its ok as sys_exit is noreturn, 3168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * so we can never come back to this non-existent exec page 3178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 3188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd MOD_DEC_USE_COUNT; 3198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddextern void * sys_call_table[]; 3228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* FIXME: Now that I'm never trying to do a C-level call through these 3248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * pointers, I should just save, intercept, and restore with void * 3258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * instead of the void * part of the function descriptor, I think. 3268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 3278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid op_save_syscalls(void) 3298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fdesc_clone.ip = sys_call_table[__NR_clone - __NR_ni_syscall]; 3318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd old_sys_clone = (void *)&fdesc_clone; 3328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fdesc_clone2.ip = sys_call_table[__NR_clone2 - __NR_ni_syscall]; 3338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd old_sys_clone2 = (void *)&fdesc_clone2; 3348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fdesc_execve.ip = sys_call_table[__NR_execve - __NR_ni_syscall]; 3358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd old_sys_execve = (void *)&fdesc_execve; 3368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fdesc_mmap.ip = sys_call_table[__NR_mmap - __NR_ni_syscall]; 3378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd old_sys_mmap = (void *)&fdesc_mmap; 3388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fdesc_mmap2.ip = sys_call_table[__NR_mmap2 - __NR_ni_syscall]; 3398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd old_sys_mmap2 = (void *)&fdesc_mmap2; 3408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fdesc_init_module.ip = sys_call_table[__NR_init_module - __NR_ni_syscall]; 3418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd old_sys_init_module = (void *)&fdesc_init_module; 3428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fdesc_exit.ip = sys_call_table[__NR_exit - __NR_ni_syscall]; 3438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd old_sys_exit = (void *)&fdesc_exit; 3448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid op_intercept_syscalls(void) 3478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* Must extract the function address from the stub function 3498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * descriptors. 3508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 3518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_clone - __NR_ni_syscall] = 3528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)post_stub_clone)->ip; 3538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_clone2 - __NR_ni_syscall] = 3548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)post_stub_clone2)->ip; 3558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_execve - __NR_ni_syscall] = 3568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)my_ia64_execve)->ip; 3578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_mmap - __NR_ni_syscall] = 3588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)post_stub_mmap)->ip; 3598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_mmap2 - __NR_ni_syscall] = 3608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)post_stub_mmap2)->ip; 3618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_init_module - __NR_ni_syscall] = 3628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)post_stub_init_module)->ip; 3638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_exit - __NR_ni_syscall] = 3648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)pre_stub_exit)->ip; 3658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid op_restore_syscalls(void) 3688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_clone - __NR_ni_syscall] = 3708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)old_sys_clone)->ip; 3718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_clone2 - __NR_ni_syscall] = 3728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)old_sys_clone2)->ip; 3738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_execve - __NR_ni_syscall] = 3748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)old_sys_execve)->ip; 3758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_mmap - __NR_ni_syscall] = 3768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)old_sys_mmap)->ip; 3778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_mmap2 - __NR_ni_syscall] = 3788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)old_sys_mmap2)->ip; 3798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_init_module - __NR_ni_syscall] = 3808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)old_sys_init_module)->ip; 3818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sys_call_table[__NR_exit - __NR_ni_syscall] = 3828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ((struct fdesc *)old_sys_exit)->ip; 3838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 384