mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-22 17:23:06 +00:00
4031093848
I wanted to make REUSE pass, but I'm not sure what to do about trivial files. REUSE suggests using CC0, but Fedora no longer allows CC0. I'll punt that until later. For now, let's add notices to some code files. Signed-off-by: Omar Sandoval <osandov@osandov.com>
108 lines
3.0 KiB
Plaintext
108 lines
3.0 KiB
Plaintext
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
static struct drgn_error *parse_vmcoreinfo_u64(const char *value,
|
|
const char *newline, int base,
|
|
uint64_t *ret)
|
|
{
|
|
errno = 0;
|
|
char *end;
|
|
*ret = strtoull(value, &end, base);
|
|
if (errno == ERANGE) {
|
|
return drgn_error_create(DRGN_ERROR_OVERFLOW,
|
|
"number in VMCOREINFO is too large");
|
|
} else if (errno || end == value || end != newline) {
|
|
return drgn_error_create(DRGN_ERROR_OTHER,
|
|
"number in VMCOREINFO is invalid");
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
struct drgn_error *drgn_program_parse_vmcoreinfo(struct drgn_program *prog,
|
|
const char *desc,
|
|
size_t descsz)
|
|
{
|
|
struct drgn_error *err;
|
|
for (const char *line = desc, *end = &desc[descsz], *newline;
|
|
(newline = memchr(line, '\n', end - line));
|
|
line = newline + 1) {
|
|
const char *equals = memchr(line, '=', newline - line);
|
|
if (!equals)
|
|
continue;
|
|
|
|
const char *value = equals + 1;
|
|
@memswitch (line, equals - line)@
|
|
@case "OSRELEASE"@
|
|
if ((size_t)(newline - value) >=
|
|
sizeof(prog->vmcoreinfo.osrelease)) {
|
|
return drgn_error_create(DRGN_ERROR_OTHER,
|
|
"OSRELEASE in VMCOREINFO is too long");
|
|
}
|
|
memcpy(prog->vmcoreinfo.osrelease, value,
|
|
newline - value);
|
|
prog->vmcoreinfo.osrelease[newline - value] = '\0';
|
|
break;
|
|
@case "PAGESIZE"@
|
|
err = parse_vmcoreinfo_u64(value, newline, 0,
|
|
&prog->vmcoreinfo.page_size);
|
|
if (err)
|
|
return err;
|
|
break;
|
|
@case "KERNELOFFSET"@
|
|
err = parse_vmcoreinfo_u64(value, newline, 16,
|
|
&prog->vmcoreinfo.kaslr_offset);
|
|
if (err)
|
|
return err;
|
|
break;
|
|
@case "SYMBOL(swapper_pg_dir)"@
|
|
err = parse_vmcoreinfo_u64(value, newline, 16,
|
|
&prog->vmcoreinfo.swapper_pg_dir);
|
|
if (err)
|
|
return err;
|
|
break;
|
|
@case "LENGTH(mem_section)"@
|
|
err = parse_vmcoreinfo_u64(value, newline, 0,
|
|
&prog->vmcoreinfo.mem_section_length);
|
|
if (err)
|
|
return err;
|
|
break;
|
|
@case "NUMBER(pgtable_l5_enabled)"@
|
|
{
|
|
uint64_t tmp;
|
|
err = parse_vmcoreinfo_u64(value, newline, 0, &tmp);
|
|
if (err)
|
|
return err;
|
|
prog->vmcoreinfo.pgtable_l5_enabled = tmp;
|
|
break;
|
|
}
|
|
@case "NUMBER(KERNELPACMASK)"@
|
|
err = parse_vmcoreinfo_u64(value, newline, 16,
|
|
&prog->aarch64_insn_pac_mask);
|
|
if (err)
|
|
return err;
|
|
break;
|
|
@case "NUMBER(VA_BITS)"@
|
|
err = parse_vmcoreinfo_u64(value, newline, 0,
|
|
&prog->vmcoreinfo.va_bits);
|
|
if (err)
|
|
return err;
|
|
break;
|
|
@endswitch@
|
|
}
|
|
if (!prog->vmcoreinfo.osrelease[0]) {
|
|
return drgn_error_create(DRGN_ERROR_OTHER,
|
|
"VMCOREINFO does not contain valid OSRELEASE");
|
|
}
|
|
if (!is_power_of_two(prog->vmcoreinfo.page_size)) {
|
|
return drgn_error_create(DRGN_ERROR_OTHER,
|
|
"VMCOREINFO does not contain valid PAGESIZE");
|
|
}
|
|
prog->vmcoreinfo.page_shift = ctz(prog->vmcoreinfo.page_size);
|
|
if (!prog->vmcoreinfo.swapper_pg_dir) {
|
|
return drgn_error_create(DRGN_ERROR_OTHER,
|
|
"VMCOREINFO does not contain valid swapper_pg_dir");
|
|
}
|
|
// Everything else is optional.
|
|
return NULL;
|
|
}
|