LINUX和FREEBSD在BSS结束地址(也可以说是malloc分配的起始地址)处理方面的不同:
LINUX:
malloc分配的起始地址是通过sys_brk(0)从内核获取,见代码
asmlinkage unsigned long sys_brk(unsigned long brk)
207 {
208 unsigned long rlim, retval;
209 unsigned long newbrk, oldbrk;
210 struct mm_struct *mm = current->mm;
211
212 down_write(&mm->mmap_sem);
213
214 if (brk <>end_code) <------------- 这里
215 goto out; <------------- 这里
216 newbrk = PAGE_ALIGN(brk);
217 oldbrk = PAGE_ALIGN(mm->brk);
218 if (oldbrk == newbrk)
219 goto set_brk;
220
221 /* Always allow shrinking brk. */
222 if (brk <= mm->brk) {
223 if (!do_munmap(mm, newbrk, oldbrk-newbrk))
224 goto set_brk;
225 goto out;
226 }
227
228 /* Check against rlimit.. */
229 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
230 if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
231 goto out;
232
233 /* Check against existing mmap mappings. */
234 if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
235 goto out;
236
237 /* Ok, looks good - let it rip. */
238 if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk)
239 goto out;
240 set_brk:
241 mm->brk = brk;
242 out: <------------- 这里
243 retval = mm->brk; <------------- 这里
244 up_write(&mm->mmap_sem);
245 return retval;
246 }
FREEBSD:
malloc分配的起始地址是硬编码在binary中,见代码:
#if defined(SYSLIBC_SCCS) && !defined(lint)
.asciz "@(#)brk.s 5.2 (Berkeley) 12/17/90"
#endif /* SYSLIBC_SCCS and not lint */
#include
__FBSDID("$FreeBSD: src/lib/libc/i386/sys/brk.S,v 1.10 2002/03/23 02:10:28 obrien Exp $");
#include "SYS.h"
.globl HIDENAME(curbrk)
.globl HIDENAME(minbrk)
ENTRY(_brk)
jmp ok
ENTRY(brk)
#ifdef PIC
movl 4(%esp),%eax
PIC_PROLOGUE
movl PIC_GOT(HIDENAME(curbrk)),%edx # set up GOT addressing <------------- 这里
movl PIC_GOT(HIDENAME(minbrk)),%ecx # PIC_EPILOGUE <------------- 这里
cmpl %eax,(%ecx)
jbe ok
movl (%ecx),%eax
movl %eax,4(%esp)
ok:
mov $SYS_break,%eax <------------- 这里
KERNCALL
jb err
movl 4(%esp),%eax
movl %eax,(%edx)
movl $0,%eax
ret
err:
PIC_PROLOGUE
jmp PIC_PLT(HIDENAME(cerror))
#else
movl 4(%esp),%eax
cmpl %eax,HIDENAME(minbrk)
jbe ok
movl HIDENAME(minbrk),%eax
movl %eax,4(%esp)
ok:
mov $SYS_break,%eax
KERNCALL
jb err
movl 4(%esp),%eax
movl %eax,HIDENAME(curbrk)
movl $0,%eax
ret
err:
jmp HIDENAME(cerror)
#endif
因此,要对堆内存分配的起始地址进行随机,在LINUX只需在内核修改brk的初始值,而在FREEBSD中则必需在用户层做处理(可以改libc或ld)。
没有评论:
发表评论