Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/kern_dump.c
Show First 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | |||||
dumpsys_gen_write_aux_headers(struct dumperinfo *di) | dumpsys_gen_write_aux_headers(struct dumperinfo *di) | ||||
{ | { | ||||
return (0); | return (0); | ||||
} | } | ||||
#endif | #endif | ||||
int | int | ||||
dumpsys_buf_seek(struct dumperinfo *di, size_t sz) | |||||
{ | |||||
static uint8_t buf[DEV_BSIZE]; | |||||
size_t nbytes; | |||||
int error; | |||||
bzero(buf, sizeof(buf)); | |||||
while (sz > 0) { | |||||
nbytes = MIN(sz, sizeof(buf)); | |||||
error = dump_write(di, buf, 0, dumplo, nbytes); | |||||
if (error) | |||||
return (error); | |||||
dumplo += nbytes; | |||||
sz -= nbytes; | |||||
} | |||||
return (0); | |||||
} | |||||
int | |||||
dumpsys_buf_write(struct dumperinfo *di, char *ptr, size_t sz) | dumpsys_buf_write(struct dumperinfo *di, char *ptr, size_t sz) | ||||
{ | { | ||||
size_t len; | size_t len; | ||||
int error; | int error; | ||||
while (sz) { | while (sz) { | ||||
len = di->blocksize - fragsz; | len = di->blocksize - fragsz; | ||||
if (len > sz) | if (len > sz) | ||||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
dumpsys_generic(struct dumperinfo *di) | dumpsys_generic(struct dumperinfo *di) | ||||
{ | { | ||||
static struct kerneldumpheader kdh; | static struct kerneldumpheader kdh; | ||||
Elf_Ehdr ehdr; | Elf_Ehdr ehdr; | ||||
uint64_t dumpsize; | uint64_t dumpsize; | ||||
off_t hdrgap; | off_t hdrgap; | ||||
size_t hdrsz, size; | size_t hdrsz; | ||||
int error; | int error; | ||||
#ifndef __powerpc__ | #ifndef __powerpc__ | ||||
if (do_minidump) | if (do_minidump) | ||||
return (minidumpsys(di)); | return (minidumpsys(di)); | ||||
#endif | #endif | ||||
bzero(&ehdr, sizeof(ehdr)); | bzero(&ehdr, sizeof(ehdr)); | ||||
Show All 24 Lines | #endif | ||||
ehdr.e_phnum = dumpsys_foreach_chunk(cb_size, &dumpsize) + | ehdr.e_phnum = dumpsys_foreach_chunk(cb_size, &dumpsize) + | ||||
DUMPSYS_NUM_AUX_HDRS; | DUMPSYS_NUM_AUX_HDRS; | ||||
hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize; | hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize; | ||||
fileofs = MD_ALIGN(hdrsz); | fileofs = MD_ALIGN(hdrsz); | ||||
dumpsize += fileofs; | dumpsize += fileofs; | ||||
hdrgap = fileofs - roundup2((off_t)hdrsz, di->blocksize); | hdrgap = fileofs - roundup2((off_t)hdrsz, di->blocksize); | ||||
/* Determine dump offset on device. */ | /* Determine dump offset on device. */ | ||||
if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2) { | if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2 + | ||||
kerneldumpcrypto_dumpkeysize(di->kdc)) { | |||||
error = ENOSPC; | error = ENOSPC; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
dumplo = di->mediaoffset + di->mediasize - dumpsize; | dumplo = di->mediaoffset + di->mediasize - dumpsize; | ||||
dumplo -= di->blocksize * 2; | dumplo -= di->blocksize * 2; | ||||
dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc); | |||||
/* Initialize kernel dump crypto. */ | |||||
error = kerneldumpcrypto_init(di->kdc); | |||||
if (error) | |||||
goto fail; | |||||
mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, dumpsize, | mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, dumpsize, | ||||
di->blocksize); | kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize); | ||||
printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20, | printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20, | ||||
ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS); | ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS); | ||||
/* Dump leader */ | /* Dump leader */ | ||||
error = dump_write_pad(di, &kdh, 0, dumplo, sizeof(kdh), &size); | error = dump_write_header(di, &kdh, 0, dumplo); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
dumplo += size; | dumplo += di->blocksize; | ||||
/* Dump key */ | |||||
error = dump_write_key(di, 0, dumplo); | |||||
if (error) | |||||
goto fail; | |||||
dumplo += kerneldumpcrypto_dumpkeysize(di->kdc); | |||||
/* Dump ELF header */ | /* Dump ELF header */ | ||||
error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr)); | error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr)); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* Dump program headers */ | /* Dump program headers */ | ||||
error = dumpsys_foreach_chunk(cb_dumphdr, di); | error = dumpsys_foreach_chunk(cb_dumphdr, di); | ||||
if (error < 0) | if (error < 0) | ||||
goto fail; | goto fail; | ||||
error = dumpsys_write_aux_headers(di); | error = dumpsys_write_aux_headers(di); | ||||
if (error < 0) | if (error < 0) | ||||
goto fail; | goto fail; | ||||
dumpsys_buf_flush(di); | dumpsys_buf_flush(di); | ||||
/* | /* | ||||
* All headers are written using blocked I/O, so we know the | * All headers are written using blocked I/O, so we know the | ||||
* current offset is (still) block aligned. Skip the alignement | * current offset is (still) block aligned. Skip the alignement | ||||
* in the file to have the segment contents aligned at page | * in the file to have the segment contents aligned at page | ||||
* boundary. We cannot use MD_ALIGN on dumplo, because we don't | * boundary. We cannot use MD_ALIGN on dumplo, because we don't | ||||
* care and may very well be unaligned within the dump device. | * care and may very well be unaligned within the dump device. | ||||
*/ | */ | ||||
dumplo += hdrgap; | error = dumpsys_buf_seek(di, (size_t)hdrgap); | ||||
if (error) | |||||
goto fail; | |||||
/* Dump memory chunks (updates dumplo) */ | /* Dump memory chunks (updates dumplo) */ | ||||
error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di); | error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di); | ||||
if (error < 0) | if (error < 0) | ||||
goto fail; | goto fail; | ||||
/* Dump trailer */ | /* Dump trailer */ | ||||
error = dump_write_pad(di, &kdh, 0, dumplo, sizeof(kdh), &size); | error = dump_write_header(di, &kdh, 0, dumplo); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
dumplo += di->blocksize; | |||||
/* Signal completion, signoff and exit stage left. */ | /* Signal completion, signoff and exit stage left. */ | ||||
dump_write(di, NULL, 0, 0, 0); | dump_write(di, NULL, 0, 0, 0); | ||||
printf("\nDump complete\n"); | printf("\nDump complete\n"); | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
if (error < 0) | if (error < 0) | ||||
Show All 11 Lines |