Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP4:Update
libkdumpfile.36085
elfdump-Support-makedumpfile-flattened-dumps.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File elfdump-Support-makedumpfile-flattened-dumps.patch of Package libkdumpfile.36085
From: Petr Tesarik <petr@tesarici.cz> Date: Fri, 27 Sep 2024 10:42:26 +0200 Subject: elfdump: Support makedumpfile flattened dumps References: bsc#1223399 Upstream: merged Git-commit: b76dc429a4d3d09fbb227fd84135cccc6bf5ee8d Allow to read ELF dumps in the flattened format, which can be produced with "makedumpfile -E -F". Extend the elf-basic test to accept extra parameters for mkelf. Add a derived test which sets "flattened = yes" and call it elf-basic-flat. [ ptesarik: Drop tests and NEWS. Tests would require backporting many additional patches, and NEWS is pointless. ] Signed-off-by: Petr Tesarik <ptesarik@suse.com> --- src/kdumpfile/elfdump.c | 125 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 86 insertions(+), 39 deletions(-) create mode 100755 tests/elf-basic-flat --- a/src/kdumpfile/elfdump.c +++ b/src/kdumpfile/elfdump.c @@ -138,6 +138,9 @@ struct elfdump_priv { /** File offset of Xen page map (xc_core) */ off_t xen_map_offset; + + /** File offset mappings for flattened files. */ + struct flattened_map *flatmap; }; static void elf_cleanup(struct kdump_shared *shared); @@ -165,6 +168,44 @@ mach2arch(unsigned mach, int elfclass) } } +/** Read buffer from an ELF dump file. + * @param flatmap Flattened offset map. + * @param buf Target I/O buffer. + * @param len Length of data. + * @param pos File position. + * @returns Error status. + * + * Read data from an ELF dump file. If the file is flattened, interpret + * @p pos as if it was already rearranged. + */ +static inline kdump_status +elfdump_pread(struct flattened_map *flatmap, void *buf, size_t len, + off_t pos) +{ + return flatmap_isflattened(flatmap) + ? flatmap_pread(flatmap, buf, len, pos) + : fcache_pread(flatmap->fcache, buf, len, pos); +} + +/** Get a contiguous data chunk from an ELF dump file. + * @param flatmap Flattened offset map. + * @param fch File cache chunk, updated on success. + * @param len Length of data. + * @param pos File position. + * @returns Error status. + * + * Get a contiguous data chunk from an ELF dump file. If the file is + * flattened, interpret @p pos as if it was already rearranged. + */ +static inline kdump_status +elfdump_get_chunk(struct flattened_map *flatmap, struct fcache_chunk *fch, + size_t len, off_t pos) +{ + return flatmap_isflattened(flatmap) + ? flatmap_get_chunk(flatmap, fch, len, pos) + : fcache_get_chunk(flatmap->fcache, fch, len, pos); +} + /** Find the LOAD segment that is closest to a physical address. * @param edp ELF dump private data. * @param paddr Requested physical address. @@ -260,8 +301,7 @@ elf_read_page(kdump_ctx_t *ctx, struct p if (size > loadaddr + pls->filesz - addr) size = loadaddr + pls->filesz - addr; - status = fcache_pread(ctx->shared->fcache, - p, size, pos); + status = elfdump_pread(edp->flatmap, p, size, pos); if (status != KDUMP_OK) goto err_read; p += size; @@ -334,8 +374,8 @@ elf_get_page(kdump_ctx_t *ctx, struct pa return cache_get_page(ctx, pio, elf_read_page); mutex_lock(&ctx->shared->cache_lock); - status = fcache_get_chunk(ctx->shared->fcache, &pio->chunk, sz, - pls->file_offset + addr - loadaddr); + status = elfdump_get_chunk(edp->flatmap, &pio->chunk, sz, + pls->file_offset + addr - loadaddr); mutex_unlock(&ctx->shared->cache_lock); return status; } @@ -745,7 +785,7 @@ xc_p2m_first_step(addrxlat_step_t *step, pos = edp->xen_map_offset + idx * sizeof(struct xen_p2m); mutex_lock(&shared->cache_lock); - status = fcache_pread(shared->fcache, &p2m, sizeof p2m, pos); + status = elfdump_pread(edp->flatmap, &p2m, sizeof p2m, pos); mutex_unlock(&shared->cache_lock); if (status != KDUMP_OK) return addrxlat_ctx_err(step->ctx, ADDRXLAT_ERR_NODATA, @@ -783,7 +823,7 @@ xc_m2p_first_step(addrxlat_step_t *step, pos = edp->xen_map_offset + idx * sizeof(struct xen_p2m); mutex_lock(&shared->cache_lock); - status = fcache_pread(shared->fcache, &p2m, sizeof p2m, pos); + status = elfdump_pread(edp->flatmap, &p2m, sizeof p2m, pos); mutex_unlock(&shared->cache_lock); if (status != KDUMP_OK) return addrxlat_ctx_err(step->ctx, ADDRXLAT_ERR_NODATA, @@ -887,8 +927,8 @@ xc_get_page(kdump_ctx_t *ctx, struct pag offset = edp->xen_pages_offset + ((off_t)idx << get_page_shift(ctx)); mutex_lock(&ctx->shared->cache_lock); - status = fcache_get_chunk(ctx->shared->fcache, &pio->chunk, - get_page_size(ctx), offset); + status = elfdump_get_chunk(edp->flatmap, &pio->chunk, + get_page_size(ctx), offset); mutex_unlock(&ctx->shared->cache_lock); return status; } @@ -988,8 +1028,8 @@ init_strtab(kdump_ctx_t *ctx, unsigned s if (!edp->strtab) return KDUMP_ERR_SYSTEM; - status = fcache_pread(ctx->shared->fcache, edp->strtab, - ps->size, ps->file_offset); + status = elfdump_pread(edp->flatmap, edp->strtab, ps->size, + ps->file_offset); if (status != KDUMP_OK) { free(edp->strtab); edp->strtab = NULL; @@ -1027,9 +1067,9 @@ init_elf32(kdump_ctx_t *ctx, Elf32_Ehdr if (offset != 0 && (shnum == 0 || phnum == PN_XNUM)) { Elf32_Shdr *sect; - ret = fcache_get_chunk(ctx->shared->fcache, &fch, - dump16toh(ctx, ehdr->e_shentsize), - offset); + ret = elfdump_get_chunk(edp->flatmap, &fch, + dump16toh(ctx, ehdr->e_shentsize), + offset); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read ELF %s #%d at %llu", @@ -1059,8 +1099,7 @@ init_elf32(kdump_ctx_t *ctx, Elf32_Ehdr Elf32_Phdr *prog; struct load_segment *pls; - ret = fcache_get_chunk(ctx->shared->fcache, &fch, - entsz, offset); + ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read ELF %s #%" PRIu32 " at %llu", @@ -1087,8 +1126,7 @@ init_elf32(kdump_ctx_t *ctx, Elf32_Ehdr for (i = 0; i < shnum; ++i) { Elf32_Shdr *sect; - ret = fcache_get_chunk(ctx->shared->fcache, &fch, - entsz, offset); + ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read ELF %s #%" PRIu32 " at %llu", @@ -1129,9 +1167,9 @@ init_elf64(kdump_ctx_t *ctx, Elf64_Ehdr if (offset != 0 && (shnum == 0 || phnum == PN_XNUM)) { Elf64_Shdr *sect; - ret = fcache_get_chunk(ctx->shared->fcache, &fch, - dump16toh(ctx, ehdr->e_shentsize), - offset); + ret = elfdump_get_chunk(edp->flatmap, &fch, + dump16toh(ctx, ehdr->e_shentsize), + offset); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read ELF %s #%d at %llu", @@ -1161,8 +1199,7 @@ init_elf64(kdump_ctx_t *ctx, Elf64_Ehdr Elf64_Phdr *prog; struct load_segment *pls; - ret = fcache_get_chunk(ctx->shared->fcache, &fch, - entsz, offset); + ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read ELF %s #%" PRIu64 " at %llu", @@ -1189,8 +1226,7 @@ init_elf64(kdump_ctx_t *ctx, Elf64_Ehdr for (i = 0; i < shnum; ++i) { Elf64_Shdr *sect; - ret = fcache_get_chunk(ctx->shared->fcache, &fch, - entsz, offset); + ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read ELF %s #%" PRIu64 " at %llu", @@ -1226,8 +1262,8 @@ walk_elf_notes(kdump_ctx_t *ctx, walk_no for (i = 0; i < edp->num_note_segments; ++i) { struct load_segment *seg = edp->note_segments + i; - ret = fcache_get_chunk(ctx->shared->fcache, &fch, - seg->filesz, seg->file_offset); + ret = elfdump_get_chunk(edp->flatmap, &fch, seg->filesz, + seg->file_offset); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read ELF notes at %llu", @@ -1369,8 +1405,8 @@ open_common(kdump_ctx_t *ctx) return set_error(ctx, ret, "Cannot create Xen PFN map"); } else if (!strcmp(name, ".note.Xen")) { - ret = fcache_get_chunk(ctx->shared->fcache, &fch, - sect->size, sect->file_offset); + ret = elfdump_get_chunk(edp->flatmap, &fch, sect->size, + sect->file_offset); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read '%s'", name); @@ -1380,8 +1416,8 @@ open_common(kdump_ctx_t *ctx) return set_error(ctx, ret, "Cannot process Xen notes"); } else if (!strcmp(name, ".xen_prstatus")) { - ret = fcache_get_chunk(ctx->shared->fcache, &fch, - sect->size, sect->file_offset); + ret = elfdump_get_chunk(edp->flatmap, &fch, sect->size, + sect->file_offset); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read '%s'", name); @@ -1413,21 +1449,15 @@ open_common(kdump_ctx_t *ctx) static kdump_status do_probe(kdump_ctx_t *ctx, void *hdr) { + struct elfdump_priv *edp = ctx->shared->fmtdata; unsigned char *eheader = hdr; Elf32_Ehdr *elf32 = hdr; Elf64_Ehdr *elf64 = hdr; - struct elfdump_priv *edp; if (memcmp(eheader, ELFMAG, SELFMAG)) return set_error(ctx, KDUMP_NOPROBE, "Invalid ELF signature"); - edp = calloc(1, sizeof *edp); - if (!edp) - return set_error(ctx, KDUMP_ERR_SYSTEM, - "Cannot allocate ELF dump private data"); - ctx->shared->fmtdata = edp; - switch (eheader[EI_DATA]) { case ELFDATA2LSB: set_byte_order(ctx, KDUMP_LITTLE_ENDIAN); @@ -1462,11 +1492,27 @@ do_probe(kdump_ctx_t *ctx, void *hdr) static kdump_status elf_probe(kdump_ctx_t *ctx) { + struct elfdump_priv *edp; struct fcache_chunk fch; kdump_status ret; - ret = fcache_get_chunk(ctx->shared->fcache, &fch, - sizeof(Elf64_Ehdr), 0); + edp = calloc(1, sizeof *edp); + if (!edp) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate ELF dump private data"); + ctx->shared->fmtdata = edp; + + edp->flatmap = flatmap_alloc(); + if (!edp->flatmap) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate %s", + "flattened dump maps"); + + ret = flatmap_init(edp->flatmap, ctx); + if (ret != KDUMP_OK) + return ret; + + ret = elfdump_get_chunk(edp->flatmap, &fch, sizeof(Elf64_Ehdr), 0); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read dump header"); @@ -1498,6 +1544,7 @@ elf_cleanup(struct kdump_shared *shared) free(edp->strtab); pfn2idx_map_free(&edp->xen_pfnmap); pfn2idx_map_free(&edp->xen_mfnmap); + flatmap_free(edp->flatmap); free(edp); shared->fmtdata = NULL; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor