elf-fdpic.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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/mm.h>
  13. #include <linux/fs.h>
  14. #include <linux/elf-fdpic.h>
  15. #include <asm/mman.h>
  16. /*****************************************************************************/
  17. /*
  18. * lay out the userspace VM according to our grand design
  19. */
  20. #ifdef CONFIG_MMU
  21. void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
  22. struct elf_fdpic_params *interp_params,
  23. unsigned long *start_stack,
  24. unsigned long *start_brk)
  25. {
  26. *start_stack = 0x02200000UL;
  27. /* if the only executable is a shared object, assume that it is an interpreter rather than
  28. * a true executable, and map it such that "ld.so --list" comes out right
  29. */
  30. if (!(interp_params->flags & ELF_FDPIC_FLAG_PRESENT) &&
  31. exec_params->hdr.e_type != ET_EXEC
  32. ) {
  33. exec_params->load_addr = PAGE_SIZE;
  34. *start_brk = 0x80000000UL;
  35. }
  36. else {
  37. exec_params->load_addr = 0x02200000UL;
  38. if ((exec_params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) ==
  39. ELF_FDPIC_FLAG_INDEPENDENT
  40. ) {
  41. exec_params->flags &= ~ELF_FDPIC_FLAG_ARRANGEMENT;
  42. exec_params->flags |= ELF_FDPIC_FLAG_CONSTDISP;
  43. }
  44. }
  45. } /* end elf_fdpic_arch_lay_out_mm() */
  46. #endif
  47. /*****************************************************************************/
  48. /*
  49. * place non-fixed mmaps firstly in the bottom part of memory, working up, and then in the top part
  50. * of memory, working down
  51. */
  52. unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len,
  53. unsigned long pgoff, unsigned long flags)
  54. {
  55. struct vm_area_struct *vma;
  56. struct vm_unmapped_area_info info;
  57. if (len > TASK_SIZE)
  58. return -ENOMEM;
  59. /* handle MAP_FIXED */
  60. if (flags & MAP_FIXED)
  61. return addr;
  62. /* only honour a hint if we're not going to clobber something doing so */
  63. if (addr) {
  64. addr = PAGE_ALIGN(addr);
  65. vma = find_vma(current->mm, addr);
  66. if (TASK_SIZE - len >= addr &&
  67. (!vma || addr + len <= vm_start_gap(vma)))
  68. goto success;
  69. }
  70. /* search between the bottom of user VM and the stack grow area */
  71. info.flags = 0;
  72. info.length = len;
  73. info.low_limit = PAGE_SIZE;
  74. info.high_limit = (current->mm->start_stack - 0x00200000);
  75. info.align_mask = 0;
  76. info.align_offset = 0;
  77. addr = vm_unmapped_area(&info);
  78. if (!(addr & ~PAGE_MASK))
  79. goto success;
  80. VM_BUG_ON(addr != -ENOMEM);
  81. /* search from just above the WorkRAM area to the top of memory */
  82. info.low_limit = PAGE_ALIGN(0x80000000);
  83. info.high_limit = TASK_SIZE;
  84. addr = vm_unmapped_area(&info);
  85. if (!(addr & ~PAGE_MASK))
  86. goto success;
  87. VM_BUG_ON(addr != -ENOMEM);
  88. #if 0
  89. printk("[area] l=%lx (ENOMEM) f='%s'\n",
  90. len, filp ? filp->f_path.dentry->d_name.name : "");
  91. #endif
  92. return -ENOMEM;
  93. success:
  94. #if 0
  95. printk("[area] l=%lx ad=%lx f='%s'\n",
  96. len, addr, filp ? filp->f_path.dentry->d_name.name : "");
  97. #endif
  98. return addr;
  99. } /* end arch_get_unmapped_area() */