void
elf32phdr(ElfPhdr *e)
{
+ int frag;
+
+ if(e->type == PT_LOAD) {
+ // Correct ELF loaders will do this implicitly,
+ // but buggy ELF loaders like the one in some
+ // versions of QEMU won't.
+ frag = e->vaddr&(e->align-1);
+ e->off -= frag;
+ e->vaddr -= frag;
+ e->paddr -= frag;
+ e->filesz += frag;
+ e->memsz += frag;
+ }
LPUT(e->type);
LPUT(e->off);
LPUT(e->vaddr);
enum
{
ENOMEM = 12,
+ _PAGE_SIZE = 4096,
};
static int32
addrspace_free(void *v, uintptr n)
{
- uintptr page_size = 4096;
+ int32 errval;
+ uintptr chunk;
uintptr off;
- int8 one_byte;
+ static byte vec[4096];
- for(off = 0; off < n; off += page_size) {
- int32 errval = runtime·mincore((int8 *)v + off, page_size, (void *)&one_byte);
+ for(off = 0; off < n; off += chunk) {
+ chunk = _PAGE_SIZE * sizeof vec;
+ if(chunk > (n - off))
+ chunk = n - off;
+ errval = runtime·mincore((int8*)v + off, chunk, vec);
// errval is 0 if success, or -(error_code) if error.
if (errval == 0 || errval != -ENOMEM)
return 0;
}
- USED(v);
- USED(n);
return 1;
}
return v;
p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
- if(p < (void*)4096) {
+ if((uintptr)p < 4096 || -(uintptr)p < 4096) {
return nil;
}
return p;
byte *p;
uintptr arena_size, bitmap_size;
extern byte end[];
+ byte *want;
runtime·InitSizes();
// not as an absolute requirement. If we ask for the end
// of the data segment but the operating system requires
// a little more space before we can start allocating, it will
- // give out a slightly higher pointer. That's fine.
- // Run with what we get back.
- p = runtime·SysReserve(end, bitmap_size + arena_size);
+ // give out a slightly higher pointer. Except QEMU, which
+ // is buggy, as usual: it won't adjust the pointer upward.
+ // So adjust it upward a little bit ourselves: 1/4 MB to get
+ // away from the running binary image and then round up
+ // to a MB boundary.
+ want = (byte*)(((uintptr)end + (1<<18) + (1<<20) - 1)&~((1<<20)-1));
+ p = runtime·SysReserve(want, bitmap_size + arena_size);
if(p == nil)
runtime·throw("runtime: cannot reserve arena virtual address space");
}