gpt4 book ai didi

porting - newlib 函数的页面错误

转载 作者:行者123 更新时间:2023-12-05 01:13:50 25 4
gpt4 key购买 nike

我一直在将 newlib 移植到我的非常小的内核中,但我很困惑:每当我包含一个引用系统调用的函数时,我的程序将在执行时出现页面错误。如果我调用一个不引用系统调用的函数,比如 rand(),就不会出错。

注意:通过包含,我的意思是只要函数,例如printf()fopen() 位于程序内部的某处,即使它不是通过 main() 调用的。

我遇到这个问题已经有一段时间了,不知道是什么原因造成的:

  • 我已经多次重建 newlib
  • 修改了我的 ELF 加载程序以加载来自节标题而不是程序标题的代码
  • 尝试单独构建 newlib/libgloss(失败)
  • 使用 GROUP、gcc 和 ld 通过 ld 脚本链接库(libc、libnosys)

我不太确定我还应该包含哪些其他信息,但我很乐意包含我能包含的信息。

编辑:为了验证,发生的页面错误不在失败函数的地址;它们在程序的其他地方。例如,当我调用位于 0x08048170 的 fopen() 时,我将在 0xA00A316C 处出现页面错误。

编辑 2:加载ELF的相关代码:

int krun(u8int *name) {
int fd = kopen(name);
Elf32_Ehdr *ehdr = kmalloc(sizeof(Elf32_Ehdr*));
read(fd, ehdr, sizeof(Elf32_Ehdr));

if (ehdr->e_ident[0] != 0x7F || ehdr->e_ident[1] != 'E' || ehdr->e_ident[2] != 'L' || ehdr->e_ident[3] != 'F') {
kfree(ehdr);
return -1;
}

int pheaders = ehdr->e_phnum;
int phoff = ehdr->e_phoff;
int phsize = ehdr->e_phentsize;

int sheaders = ehdr->e_shnum;
int shoff = ehdr->e_shoff;
int shsize = ehdr->e_shentsize;

for (int i = 0; i < pheaders; i++) {
lseek(fd, phoff + phsize * i, SEEK_SET);

Elf32_Phdr *phdr = kmalloc(sizeof(Elf32_Phdr*));
read(fd, phdr, sizeof(Elf32_Phdr));

u32int page = PMMAllocPage();

int flags = 0;
if (phdr->p_flags & PF_R) flags |= PAGE_PRESENT;
if (phdr->p_flags & PF_W) flags |= PAGE_WRITE;

int pages = (phdr->p_memsz / 0x1000) + 1;
while (pages >= 0) {
u32int mapaddr = (phdr->p_vaddr + (pages * 0x1000)) & 0xFFFFF000;
map(mapaddr, page, flags | PAGE_USER);
pages--;
}

lseek(fd, phdr->p_offset, SEEK_SET);
read(fd, (void *)phdr->p_vaddr, phdr->p_filesz);

kfree(phdr);
}

// Removed: code block that zeroes .bss: it's already zeroed whenever I check it anyways
// Removed: code block that creates thread and adds it to scheduler

kfree(ehdr);
return 0;
}

编辑 3:我注意到如果我调用系统调用,例如 write(),然后调用 printf() 两次或更多次,我将得到一个未知的操作码中断。奇怪的。

最佳答案

糟糕!想通了:当我映射虚拟地址时,我应该每次都分配一个新页面,如下所示:

map(mapaddr, PMMAllocPage(), flags | PAGE_USER); 

现在一切正常。

对于那些对为什么它不起作用感到好奇的人:当我不包括 printf() 时,程序的大小低于 0x1000 字节,所以只映射一页是可以的.当我包含 printf()fopen() 时,程序的大小要大得多,所以这就是导致问题的原因。

关于porting - newlib 函数的页面错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8549204/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com