![cinap_lenrek](/assets/img/avatar_default.png)
For 64-bit architectures, the a.out header has the HDR_MAGIC flag set in the magic and is expanded by 8 bytes containing the 64-bit virtual address of the programs entry point. While Exec.entry contains physical address for kernel images. Our sysexec() would always use Exec.entry, even for 64-bit a.out binaries, which worked because PADDR(entry) == entry for userspace pointers. This change fixes it, having the kernel use the 64-bit entry point and document the behaviour in the manpage.
94 lines
1.5 KiB
C
94 lines
1.5 KiB
C
#include "u.h"
|
|
#include "../port/lib.h"
|
|
#include "mem.h"
|
|
#include "dat.h"
|
|
#include "fns.h"
|
|
#include "../port/error.h"
|
|
#include "a.out.h"
|
|
|
|
static void
|
|
readn(Chan *c, void *vp, long n)
|
|
{
|
|
char *p = vp;
|
|
long nn;
|
|
|
|
while(n > 0) {
|
|
nn = devtab[c->type]->read(c, p, n, c->offset);
|
|
if(nn == 0)
|
|
error(Eshort);
|
|
c->offset += nn;
|
|
p += nn;
|
|
n -= nn;
|
|
}
|
|
}
|
|
|
|
void
|
|
rebootcmd(int argc, char *argv[])
|
|
{
|
|
struct {
|
|
Exec;
|
|
uvlong hdr[1];
|
|
} ehdr;
|
|
Chan *c;
|
|
ulong magic, text, rtext, entry, data, size, align;
|
|
uchar *p;
|
|
|
|
if(argc == 0)
|
|
exit(0);
|
|
|
|
c = namec(argv[0], Aopen, OEXEC, 0);
|
|
if(waserror()){
|
|
cclose(c);
|
|
nexterror();
|
|
}
|
|
|
|
readn(c, &ehdr, sizeof(Exec));
|
|
magic = beswal(ehdr.magic);
|
|
entry = beswal(ehdr.entry);
|
|
text = beswal(ehdr.text);
|
|
data = beswal(ehdr.data);
|
|
|
|
if(!(magic == AOUT_MAGIC)){
|
|
switch(magic){
|
|
case I_MAGIC:
|
|
case S_MAGIC:
|
|
if((I_MAGIC == AOUT_MAGIC) || (S_MAGIC == AOUT_MAGIC))
|
|
break;
|
|
default:
|
|
error(Ebadexec);
|
|
}
|
|
}
|
|
if(magic & HDR_MAGIC)
|
|
readn(c, ehdr.hdr, sizeof(ehdr.hdr));
|
|
|
|
switch(magic){
|
|
case R_MAGIC:
|
|
align = 0x10000; /* 64k segment alignment for arm64 */
|
|
break;
|
|
default:
|
|
align = BY2PG;
|
|
break;
|
|
}
|
|
|
|
/* round text out to page boundary */
|
|
rtext = ROUND(entry+text, align)-entry;
|
|
size = rtext + data;
|
|
p = malloc(size);
|
|
if(p == nil)
|
|
error(Enomem);
|
|
|
|
if(waserror()){
|
|
free(p);
|
|
nexterror();
|
|
}
|
|
|
|
memset(p, 0, size);
|
|
readn(c, p, text);
|
|
readn(c, p + rtext, data);
|
|
|
|
ksetenv("bootfile", argv[0], 1);
|
|
|
|
reboot((void*)entry, p, size);
|
|
error(Egreg);
|
|
}
|