elf-fdpic.c 3.3 KB

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