git://scm.lunaixsky.com
/
lunaix-os.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
regression: elf loading
[lunaix-os.git]
/
lunaix-os
/
kernel
/
loader
/
elf.c
diff --git
a/lunaix-os/kernel/loader/elf.c
b/lunaix-os/kernel/loader/elf.c
index 7880fe60517d7a325178165afba3e1bce0adac0b..241ddf91b253823cb88b5600b3f116cdb7ef020d 100644
(file)
--- a/
lunaix-os/kernel/loader/elf.c
+++ b/
lunaix-os/kernel/loader/elf.c
@@
-8,33
+8,27
@@
#include <lunaix/spike.h>
int
#include <lunaix/spike.h>
int
-__elf_populate_mapped(struct mm_region* region, void* pg, off_t
offset
)
+__elf_populate_mapped(struct mm_region* region, void* pg, off_t
segfoff
)
{
{
- struct elf32_phdr* phdr = (struct elf32_phdr*)region->data;
- size_t segsz = phdr->p_filesz;
- size_t segoff = offset - phdr->p_offset;
+ size_t segsz = region->flen;
+ size_t segmoff = segfoff - region->foff;
- if (segoff >= segsz) {
+ if (seg
m
off >= segsz) {
return 0;
}
struct v_file* file = region->mfile;
return 0;
}
struct v_file* file = region->mfile;
- size_t rdlen = MIN(segsz - segoff, PG_SIZE);
+ size_t rdlen = MIN(segsz - seg
m
off, PG_SIZE);
if (rdlen == PG_SIZE) {
// This is because we want to exploit any optimization on read_page
if (rdlen == PG_SIZE) {
// This is because we want to exploit any optimization on read_page
- return file->ops->read_page(file->inode, pg, PG_SIZE,
offset
);
+ return file->ops->read_page(file->inode, pg, PG_SIZE,
segfoff
);
} else {
} else {
- return file->ops->read(file->inode, pg, rdlen, offset);
+ // we don't want to over-read the segment!
+ return file->ops->read(file->inode, pg, rdlen, segfoff);
}
}
}
}
-void
-__elf_destruct_mapped(struct mm_region* region)
-{
- vfree(region->data);
-}
-
int
elf_map_segment(struct ld_param* ldparam,
struct v_file* elfile,
int
elf_map_segment(struct ld_param* ldparam,
struct v_file* elfile,
@@
-53,22
+47,22
@@
elf_map_segment(struct ld_param* ldparam,
struct mm_region* seg_reg;
struct mmap_param param = { .vms_mnt = ldparam->vms_mnt,
struct mm_region* seg_reg;
struct mmap_param param = { .vms_mnt = ldparam->vms_mnt,
- .
regions = &ldparam->proc->mm.regions
,
+ .
pvms = &ldparam->proc->mm
,
.proct = proct,
.offset = phdr->p_offset,
.proct = proct,
.offset = phdr->p_offset,
- .length = ROUNDUP(phdr->p_memsz, PG_SIZE),
- .flags =
- MAP_FIXED | MAP_PRIVATE | REGION_TYPE_CODE };
+ .mlen = ROUNDUP(phdr->p_memsz, PG_SIZE),
+ .flen = phdr->p_filesz,
+ .flags = MAP_FIXED | MAP_PRIVATE,
+ .type = REGION_TYPE_CODE };
int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdr->p_va), elfile, ¶m);
if (!status) {
int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdr->p_va), elfile, ¶m);
if (!status) {
- struct elf32_phdr* phdr_ = valloc(sizeof(SIZE_PHDR));
- *phdr_ = *phdr;
- seg_reg->data = phdr;
-
seg_reg->init_page = __elf_populate_mapped;
seg_reg->init_page = __elf_populate_mapped;
- seg_reg->destruct_region = __elf_destruct_mapped;
+
+ size_t next_addr = phdr->p_memsz + phdr->p_va;
+ ldparam->info.end = MAX(ldparam->info.end, ROUNDUP(next_addr, PG_SIZE));
+ ldparam->info.mem_sz += phdr->p_memsz;
}
return status;
}
return status;
@@
-89,18
+83,34
@@
elf_setup_mapping(struct ld_param* ldparam,
}
tbl_sz = 1 << ILOG2(tbl_sz);
}
tbl_sz = 1 << ILOG2(tbl_sz);
- phdrs = elfile->ops->read(elfile->inode, phdrs, tbl_sz, ehdr->e_phoff);
+ status = elfile->ops->read(elfile->inode, phdrs, tbl_sz, ehdr->e_phoff);
+
+ if (status < 0) {
+ goto done;
+ }
+
+ if (PG_ALIGN(phdrs[0].p_va) != USER_START) {
+ status = ENOEXEC;
+ goto done;
+ }
size_t entries = tbl_sz / SIZE_PHDR;
for (size_t i = 0; i < entries; i++) {
struct elf32_phdr* phdr = &phdrs[i];
if (phdr->p_type == PT_LOAD) {
size_t entries = tbl_sz / SIZE_PHDR;
for (size_t i = 0; i < entries; i++) {
struct elf32_phdr* phdr = &phdrs[i];
if (phdr->p_type == PT_LOAD) {
- status = elf_map_segment(ldparam, elfile, phdr);
+ if (phdr->p_align == PG_SIZE) {
+ status = elf_map_segment(ldparam, elfile, phdr);
+ } else {
+ // surprising alignment!
+ status = ENOEXEC;
+ }
}
// TODO process other types of segments
if (status) {
}
// TODO process other types of segments
if (status) {
+ // errno in the middle of mapping restructuring, it is impossible
+ // to recover!
ldparam->status |= LD_STAT_FKUP;
goto done;
}
ldparam->status |= LD_STAT_FKUP;
goto done;
}
@@
-117,7
+127,7
@@
elf_load(struct ld_param* ldparam, struct v_file* elfile)
struct elf32_ehdr* ehdr = valloc(SIZE_EHDR);
int status = elfile->ops->read(elfile->inode, ehdr, SIZE_EHDR, 0);
struct elf32_ehdr* ehdr = valloc(SIZE_EHDR);
int status = elfile->ops->read(elfile->inode, ehdr, SIZE_EHDR, 0);
- if (status) {
+ if (status
< 0
) {
goto done;
}
goto done;
}
@@
-130,7
+140,7
@@
elf_load(struct ld_param* ldparam, struct v_file* elfile)
goto done;
}
goto done;
}
- ldparam->ehdr_out = *ehdr;
+ ldparam->
info.
ehdr_out = *ehdr;
done:
vfree(ehdr);
done:
vfree(ehdr);