elf-fdpic.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /* elf-fdpic.c: ELF FDPIC memory layout management
  2. *
  3. * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/sched.h>
  12. #include <linux/sched/mm.h>
  13. #include <linux/mm.h>
  14. #include <linux/fs.h>
  15. #include <linux/elf-fdpic.h>
  16. #include <asm/mman.h>
  17. /*****************************************************************************/
  18. /*
  19. * lay out the userspace VM according to our grand design
  20. */
  21. #ifdef CONFIG_MMU
  22. void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
  23. struct elf_fdpic_params *interp_params,
  24. unsigned long *start_stack,
  25. unsigned long *start_brk)
  26. {
  27. *start_stack = 0x02200000UL;
  28. /* if the only executable is a shared object, assume that it is an interpreter rather than
  29. * a true executable, and map it such that "ld.so --list" comes out right
  30. */
  31. if (!(interp_params->flags & ELF_FDPIC_FLAG_PRESENT) &&
  32. exec_params->hdr.e_type != ET_EXEC
  33. ) {
  34. exec_params->load_addr = PAGE_SIZE;
  35. *start_brk = 0x80000000UL;
  36. }
  37. else {
  38. exec_params->load_addr = 0x02200000UL;
  39. if ((exec_params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) ==
  40. ELF_FDPIC_FLAG_INDEPENDENT
  41. ) {
  42. exec_params->flags &= ~ELF_FDPIC_FLAG_ARRANGEMENT;
  43. exec_params->flags |= ELF_FDPIC_FLAG_CONSTDISP;
  44. }
  45. }
  46. } /* end elf_fdpic_arch_lay_out_mm() */
  47. #endif
  48. /*****************************************************************************/
  49. /*
  50. * place non-fixed mmaps firstly in the bottom part of memory, working up, and then in the top part
  51. * of memory, working down
  52. */
  53. unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len,
  54. unsigned long pgoff, unsigned long flags)
  55. {
  56. struct vm_area_struct *vma;
  57. struct vm_unmapped_area_info info;
  58. if (len > TASK_SIZE)
  59. return -ENOMEM;
  60. /* handle MAP_FIXED */
  61. if (flags & MAP_FIXED)
  62. return addr;
  63. /* only honour a hint if we're not going to clobber something doing so */
  64. if (addr) {
  65. addr = PAGE_ALIGN(addr);
  66. vma = find_vma(current->mm, addr);
  67. if (TASK_SIZE - len >= addr &&
  68. (!vma || addr + len <= vma->vm_start))
  69. goto success;
  70. }
  71. /* search between the bottom of user VM and the stack grow area */
  72. info.flags = 0;
  73. info.length = len;
  74. info.low_limit = PAGE_SIZE;
  75. info.high_limit = (current->mm->start_stack - 0x00200000);
  76. info.align_mask = 0;
  77. info.align_offset = 0;
  78. addr = vm_unmapped_area(&info);
  79. if (!(addr & ~PAGE_MASK))
  80. goto success;
  81. VM_BUG_ON(addr != -ENOMEM);
  82. /* search from just above the WorkRAM area to the top of memory */
  83. info.low_limit = PAGE_ALIGN(0x80000000);
  84. info.high_limit = TASK_SIZE;
  85. addr = vm_unmapped_area(&info);
  86. if (!(addr & ~PAGE_MASK))
  87. goto success;
  88. VM_BUG_ON(addr != -ENOMEM);
  89. #if 0
  90. printk("[area] l=%lx (ENOMEM) f='%s'\n",
  91. len, filp ? filp->f_path.dentry->d_name.name : "");
  92. #endif
  93. return -ENOMEM;
  94. success:
  95. #if 0
  96. printk("[area] l=%lx ad=%lx f='%s'\n",
  97. len, addr, filp ? filp->f_path.dentry->d_name.name : "");
  98. #endif
  99. return addr;
  100. } /* end arch_get_unmapped_area() */