Je portais newlib dans mon très petit noyau, et je suis perplexe: chaque fois que inclut une fonction qui fait référence à un appel système, mon programme va signaler une erreur lors de l'exécution. Si j'appelle une fonction qui ne fait pas référence à un appel système, comme rand()
, rien ne va mal.Erreur de page avec les fonctions newlib
Note: Par inclusion, je veux dire aussi longtemps que la fonction, par ex. ou fopen()
, est quelque part dans le programme, même si elle n'est pas appelée par main()
.
J'ai eu ce problème depuis un certain temps maintenant, et ne savent pas ce qui pourrait être la cause:
- J'ai rebâti newlib plusieurs fois
- modifié mon chargeur ELF pour charger le le code des en-têtes de section au lieu d'en-têtes de programme
- ont tenté de construire newlib/libgloss séparément (qui a échoué)
- reliaient les bibliothèques (libc, libnosys) par le script en utilisant ld
GROUP
, gcc et ld
Je ne suis pas tout à fait sûr quelle autre information je devrais inclure avec ceci, mais je serais heureux d'inclure ce que je peux. Editer: Pour vérifier, les défauts de page qui se produisent ne sont pas aux adresses des fonctions défaillantes; ils sont ailleurs dans le programme. Par exemple, lorsque j'appelle fopen()
, situé à 0x08048170, je vais signaler une erreur à 0xA00A316C.
Edit 2: code approprié pour le chargement 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;
}
Edit 3: Je l'ai remarqué que si j'appelle un appel système, comme write()
, puis appeler printf()
deux fois ou plus, je obtiendra une interruption d'opcode inconnue. Impair.
Pouvez-vous exécuter l'équivalent moral de 'ldd/path/to/binary' sur un exécutable et un exécutable défaillant? – sarnold
@sarnold J'ai couru 'objdump' et' readelf' (mon environnement n'a pas 'ldd'); il n'y a pas de section dynamique, de relocalisation ou de section de déroulement dans les deux exécutables. –