elf-fdpic.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. unsigned long limit;
  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 <= vma->vm_start))
  68. goto success;
  69. }
  70. /* search between the bottom of user VM and the stack grow area */
  71. addr = PAGE_SIZE;
  72. limit = (current->mm->start_stack - 0x00200000);
  73. if (addr + len <= limit) {
  74. limit -= len;
  75. if (addr <= limit) {
  76. vma = find_vma(current->mm, PAGE_SIZE);
  77. for (; vma; vma = vma->vm_next) {
  78. if (addr > limit)
  79. break;
  80. if (addr + len <= vma->vm_start)
  81. goto success;
  82. addr = vma->vm_end;
  83. }
  84. }
  85. }
  86. /* search from just above the WorkRAM area to the top of memory */
  87. addr = PAGE_ALIGN(0x80000000);
  88. limit = TASK_SIZE - len;
  89. if (addr <= limit) {
  90. vma = find_vma(current->mm, addr);
  91. for (; vma; vma = vma->vm_next) {
  92. if (addr > limit)
  93. break;
  94. if (addr + len <= vma->vm_start)
  95. goto success;
  96. addr = vma->vm_end;
  97. }
  98. if (!vma && addr <= limit)
  99. goto success;
  100. }
  101. #if 0
  102. printk("[area] l=%lx (ENOMEM) f='%s'\n",
  103. len, filp ? filp->f_path.dentry->d_name.name : "");
  104. #endif
  105. return -ENOMEM;
  106. success:
  107. #if 0
  108. printk("[area] l=%lx ad=%lx f='%s'\n",
  109. len, addr, filp ? filp->f_path.dentry->d_name.name : "");
  110. #endif
  111. return addr;
  112. } /* end arch_get_unmapped_area() */