File flatmap-Allow-to-use-the-flatmap-API-with-non-flatte.patch of Package libkdumpfile.36085

From: Petr Tesarik <petr@tesarici.cz>
Date: Sun, 29 Sep 2024 18:01:50 +0200
Subject: flatmap: Allow to use the flatmap API with non-flattened files
References: bsc#1223399
Upstream: merged
Git-commit: bc14a715bbcc7698b25064e4b3dbafaa1ea86bcf

The flatmap API now gets enough information to know if a file is flattened
and (where appropriate) read directly from a non-flattened file. In fact,
this is what elfdump_pread() and elfdump_get_chunk() already do.

Moreover, the check adds only little overhead (especially if the function
is inline), so rename the original functions (which can read only flattened
files) by adding a _flat suffix to them and make the API usable with
non-flattened files.

Remove the format-specific diskdump and elfdump functions, which do
essentially the same job as flatmap_pread() and flatmap_get_chunk()
after this change.

Signed-off-by: Petr Tesarik <ptesarik@suse.com>
---
 src/kdumpfile/diskdump.c       |   70 ++++++++++-------------------------------
 src/kdumpfile/elfdump.c        |   70 +++++++++--------------------------------
 src/kdumpfile/flatmap.c        |    8 ++--
 src/kdumpfile/kdumpfile-priv.h |   43 ++++++++++++++++++++++++-
 4 files changed, 79 insertions(+), 112 deletions(-)

--- a/src/kdumpfile/diskdump.c
+++ b/src/kdumpfile/diskdump.c
@@ -189,47 +189,6 @@ struct setup_data {
 
 static void diskdump_cleanup(struct kdump_shared *shared);
 
-/** Read buffer from a diskdump file.
- * @param ctx   Dump file object.
- * @param buf   Target I/O buffer.
- * @param len   Length of data.
- * @param pos   File position.
- * @returns     Error status.
- *
- * Read data from a diskdump file. If the file is flattened, interpret
- * @p pos as if it was already rearranged.
- */
-static inline kdump_status
-diskdump_pread(kdump_ctx_t *ctx, void *buf, size_t len, off_t pos)
-{
-	struct disk_dump_priv *ddp = ctx->shared->fmtdata;
-
-	return flatmap_isflattened(ddp->flatmap)
-		? flatmap_pread(ddp->flatmap, buf, len, pos)
-		: fcache_pread(ctx->shared->fcache, buf, len, pos);
-}
-
-/** Get a contiguous data chunk from a diskdump file.
- * @param ctx   Dump file object.
- * @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 a diskdump file. If the file is
- * flattened, interpret @p pos as if it was already rearranged.
- */
-static inline kdump_status
-diskdump_get_chunk(kdump_ctx_t *ctx, struct fcache_chunk *fch,
-		   size_t len, off_t pos)
-{
-	struct disk_dump_priv *ddp = ctx->shared->fmtdata;
-
-	return flatmap_isflattened(ddp->flatmap)
-		? flatmap_get_chunk(ddp->flatmap, fch, len, pos)
-		: fcache_get_chunk(ctx->shared->fcache, fch, len, pos);
-}
-
 /** Add a new PFN region.
  * @param ctx  Dump file context.
  * @param rgn  PFN region.
@@ -422,7 +381,7 @@ diskdump_read_page(kdump_ctx_t *ctx, str
 	}
 
 	mutex_lock(&ctx->shared->cache_lock);
-	ret = diskdump_pread(ctx, &pd, sizeof pd, pd_pos);
+	ret = flatmap_pread(ddp->flatmap, &pd, sizeof pd, pd_pos);
 	mutex_unlock(&ctx->shared->cache_lock);
 	if (ret != KDUMP_OK)
 		return set_error(ctx, ret,
@@ -441,7 +400,7 @@ diskdump_read_page(kdump_ctx_t *ctx, str
 					 "Wrong compressed size: %lu",
 					 (unsigned long)pd.size);
 		mutex_lock(&ctx->shared->cache_lock);
-		ret = diskdump_get_chunk(ctx, &fch, pd.size, pd.offset);
+		ret = flatmap_get_chunk(ddp->flatmap, &fch, pd.size, pd.offset);
 		mutex_unlock(&ctx->shared->cache_lock);
 	} else {
 		if (pd.size != get_page_size(ctx))
@@ -449,7 +408,7 @@ diskdump_read_page(kdump_ctx_t *ctx, str
 					 "Wrong page size: %lu",
 					 (unsigned long)pd.size);
 		mutex_lock(&ctx->shared->cache_lock);
-		ret = diskdump_pread(ctx, pio->chunk.data, pd.size, pd.offset);
+		ret = flatmap_pread(ddp->flatmap, pio->chunk.data, pd.size, pd.offset);
 		mutex_unlock(&ctx->shared->cache_lock);
 	}
 
@@ -518,11 +477,12 @@ diskdump_get_page(kdump_ctx_t *ctx, stru
 static kdump_status
 read_vmcoreinfo(kdump_ctx_t *ctx, off_t off, size_t size)
 {
+	struct disk_dump_priv *ddp = ctx->shared->fmtdata;
 	struct fcache_chunk fch;
 	kdump_attr_value_t val;
 	kdump_status ret;
 
-	ret = diskdump_get_chunk(ctx, &fch, size, off);
+	ret = flatmap_get_chunk(ddp->flatmap, &fch, size, off);
 	if (ret != KDUMP_OK)
 		return set_error(ctx, ret,
 				 "Cannot read %zu VMCOREINFO bytes at %llu",
@@ -545,10 +505,11 @@ read_vmcoreinfo(kdump_ctx_t *ctx, off_t
 static kdump_status
 read_notes(kdump_ctx_t *ctx, off_t off, size_t size)
 {
+	struct disk_dump_priv *ddp = ctx->shared->fmtdata;
 	struct fcache_chunk fch;
 	kdump_status ret;
 
-	ret = diskdump_get_chunk(ctx, &fch, size, off);
+	ret = flatmap_get_chunk(ddp->flatmap, &fch, size, off);
 	if (ret != KDUMP_OK)
 		return set_error(ctx, ret,
 				 "Cannot read %zu note bytes at %llu",
@@ -621,6 +582,7 @@ static kdump_status
 read_bitmap(kdump_ctx_t *ctx, int32_t sub_hdr_size,
 	    int32_t bitmap_blocks)
 {
+	struct disk_dump_priv *ddp = ctx->shared->fmtdata;
 	off_t off = (1 + sub_hdr_size) * get_page_size(ctx);
 	off_t descoff;
 	size_t bitmapsize;
@@ -645,7 +607,7 @@ read_bitmap(kdump_ctx_t *ctx, int32_t su
 	if (get_max_pfn(ctx) > max_bitmap_pfn)
 		set_max_pfn(ctx, max_bitmap_pfn);
 
-	ret = diskdump_get_chunk(ctx, &fch, bitmapsize, off);
+	ret = flatmap_get_chunk(ddp->flatmap, &fch, bitmapsize, off);
 	if (ret != KDUMP_OK)
 		return set_error(ctx, ret,
 				 "Cannot read %zu bytes of page bitmap"
@@ -709,6 +671,7 @@ static kdump_status
 read_sub_hdr_32(struct setup_data *sdp, int32_t header_version)
 {
 	kdump_ctx_t *ctx = sdp->ctx;
+	struct disk_dump_priv *ddp = ctx->shared->fmtdata;
 	struct kdump_sub_header_32 subhdr;
 	kdump_status ret;
 
@@ -720,8 +683,8 @@ read_sub_hdr_32(struct setup_data *sdp,
 	if (header_version < 1)
 		return KDUMP_OK;
 
-	ret = diskdump_pread(ctx, &subhdr, sizeof subhdr,
-			     get_page_size(ctx));
+	ret = flatmap_pread(ddp->flatmap, &subhdr, sizeof subhdr,
+			    get_page_size(ctx));
 	if (ret != KDUMP_OK)
 		return set_error(ctx, ret,
 				 "Cannot read subheader");
@@ -792,6 +755,7 @@ static kdump_status
 read_sub_hdr_64(struct setup_data *sdp, int32_t header_version)
 {
 	kdump_ctx_t *ctx = sdp->ctx;
+	struct disk_dump_priv *ddp = ctx->shared->fmtdata;
 	struct kdump_sub_header_64 subhdr;
 	kdump_status ret;
 
@@ -803,8 +767,8 @@ read_sub_hdr_64(struct setup_data *sdp,
 	if (header_version < 1)
 		return KDUMP_OK;
 
-	ret = diskdump_pread(ctx, &subhdr, sizeof subhdr,
-			     get_page_size(ctx));
+	ret = flatmap_pread(ddp->flatmap, &subhdr, sizeof subhdr,
+			    get_page_size(ctx));
 	if (ret != KDUMP_OK)
 		return set_error(ctx, ret,
 				 "Cannot read subheader");
@@ -974,6 +938,7 @@ diskdump_probe(kdump_ctx_t *ctx)
 		{ 'K', 'D', 'U', 'M', 'P', ' ', ' ', ' ' };
 
 	char hdr[sizeof(struct disk_dump_header_64)];
+	struct disk_dump_priv *ddp;
 	char desc[32];
 	kdump_status status;
 
@@ -981,7 +946,8 @@ diskdump_probe(kdump_ctx_t *ctx)
 	if (status != KDUMP_OK)
 		return status;
 
-	status = diskdump_pread(ctx, hdr, sizeof hdr, 0);
+	ddp = ctx->shared->fmtdata;
+	status = flatmap_pread(ddp->flatmap, hdr, sizeof hdr, 0);
 	if (status != KDUMP_OK)
 		return set_error(ctx, status, "Cannot read dump header");
 
--- a/src/kdumpfile/elfdump.c
+++ b/src/kdumpfile/elfdump.c
@@ -168,44 +168,6 @@ 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.
@@ -301,7 +263,7 @@ elf_read_page(kdump_ctx_t *ctx, struct p
 			if (size > loadaddr + pls->filesz - addr)
 				size = loadaddr + pls->filesz - addr;
 
-			status = elfdump_pread(edp->flatmap, p, size, pos);
+			status = flatmap_pread(edp->flatmap, p, size, pos);
 			if (status != KDUMP_OK)
 				goto err_read;
 			p += size;
@@ -374,7 +336,7 @@ 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 = elfdump_get_chunk(edp->flatmap, &pio->chunk, sz,
+	status = flatmap_get_chunk(edp->flatmap, &pio->chunk, sz,
 				   pls->file_offset + addr - loadaddr);
 	mutex_unlock(&ctx->shared->cache_lock);
 	return status;
@@ -785,7 +747,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 = elfdump_pread(edp->flatmap, &p2m, sizeof p2m, pos);
+	status = flatmap_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,
@@ -823,7 +785,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 = elfdump_pread(edp->flatmap, &p2m, sizeof p2m, pos);
+	status = flatmap_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,
@@ -927,7 +889,7 @@ 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 = elfdump_get_chunk(edp->flatmap, &pio->chunk,
+	status = flatmap_get_chunk(edp->flatmap, &pio->chunk,
 				   get_page_size(ctx), offset);
 	mutex_unlock(&ctx->shared->cache_lock);
 	return status;
@@ -1028,7 +990,7 @@ init_strtab(kdump_ctx_t *ctx, unsigned s
 	if (!edp->strtab)
 		return KDUMP_ERR_SYSTEM;
 
-	status = elfdump_pread(edp->flatmap, edp->strtab, ps->size,
+	status = flatmap_pread(edp->flatmap, edp->strtab, ps->size,
 			       ps->file_offset);
 	if (status != KDUMP_OK) {
 		free(edp->strtab);
@@ -1067,7 +1029,7 @@ init_elf32(kdump_ctx_t *ctx, Elf32_Ehdr
 	if (offset != 0 && (shnum == 0 || phnum == PN_XNUM)) {
 		Elf32_Shdr *sect;
 
-		ret = elfdump_get_chunk(edp->flatmap, &fch,
+		ret = flatmap_get_chunk(edp->flatmap, &fch,
 					dump16toh(ctx, ehdr->e_shentsize),
 					offset);
 		if (ret != KDUMP_OK)
@@ -1099,7 +1061,7 @@ init_elf32(kdump_ctx_t *ctx, Elf32_Ehdr
 		Elf32_Phdr *prog;
 		struct load_segment *pls;
 
-		ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset);
+		ret = flatmap_get_chunk(edp->flatmap, &fch, entsz, offset);
 		if (ret != KDUMP_OK)
 			return set_error(ctx, ret,
 					 "Cannot read ELF %s #%" PRIu32 " at %llu",
@@ -1126,7 +1088,7 @@ init_elf32(kdump_ctx_t *ctx, Elf32_Ehdr
 	for (i = 0; i < shnum; ++i) {
 		Elf32_Shdr *sect;
 
-		ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset);
+		ret = flatmap_get_chunk(edp->flatmap, &fch, entsz, offset);
 		if (ret != KDUMP_OK)
 			return set_error(ctx, ret,
 					 "Cannot read ELF %s #%" PRIu32 " at %llu",
@@ -1167,7 +1129,7 @@ init_elf64(kdump_ctx_t *ctx, Elf64_Ehdr
 	if (offset != 0 && (shnum == 0 || phnum == PN_XNUM)) {
 		Elf64_Shdr *sect;
 
-		ret = elfdump_get_chunk(edp->flatmap, &fch,
+		ret = flatmap_get_chunk(edp->flatmap, &fch,
 					dump16toh(ctx, ehdr->e_shentsize),
 					offset);
 		if (ret != KDUMP_OK)
@@ -1199,7 +1161,7 @@ init_elf64(kdump_ctx_t *ctx, Elf64_Ehdr
 		Elf64_Phdr *prog;
 		struct load_segment *pls;
 
-		ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset);
+		ret = flatmap_get_chunk(edp->flatmap, &fch, entsz, offset);
 		if (ret != KDUMP_OK)
 			return set_error(ctx, ret,
 					 "Cannot read ELF %s #%" PRIu64 " at %llu",
@@ -1226,7 +1188,7 @@ init_elf64(kdump_ctx_t *ctx, Elf64_Ehdr
 	for (i = 0; i < shnum; ++i) {
 		Elf64_Shdr *sect;
 
-		ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset);
+		ret = flatmap_get_chunk(edp->flatmap, &fch, entsz, offset);
 		if (ret != KDUMP_OK)
 			return set_error(ctx, ret,
 					 "Cannot read ELF %s #%" PRIu64 " at %llu",
@@ -1262,7 +1224,7 @@ 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 = elfdump_get_chunk(edp->flatmap, &fch, seg->filesz,
+		ret = flatmap_get_chunk(edp->flatmap, &fch, seg->filesz,
 					seg->file_offset);
 		if (ret != KDUMP_OK)
 			return set_error(ctx, ret,
@@ -1405,7 +1367,7 @@ open_common(kdump_ctx_t *ctx)
 				return set_error(ctx, ret,
 						 "Cannot create Xen PFN map");
 		} else if (!strcmp(name, ".note.Xen")) {
-			ret = elfdump_get_chunk(edp->flatmap, &fch, sect->size,
+			ret = flatmap_get_chunk(edp->flatmap, &fch, sect->size,
 						sect->file_offset);
 			if (ret != KDUMP_OK)
 				return set_error(ctx, ret,
@@ -1416,7 +1378,7 @@ open_common(kdump_ctx_t *ctx)
 				return set_error(ctx, ret,
 						 "Cannot process Xen notes");
 		} else if (!strcmp(name, ".xen_prstatus")) {
-			ret = elfdump_get_chunk(edp->flatmap, &fch, sect->size,
+			ret = flatmap_get_chunk(edp->flatmap, &fch, sect->size,
 						sect->file_offset);
 			if (ret != KDUMP_OK)
 				return set_error(ctx, ret,
@@ -1512,7 +1474,7 @@ elf_probe(kdump_ctx_t *ctx)
 	if (ret != KDUMP_OK)
 		return ret;
 
-	ret = elfdump_get_chunk(edp->flatmap, &fch, sizeof(Elf64_Ehdr), 0);
+	ret = flatmap_get_chunk(edp->flatmap, &fch, sizeof(Elf64_Ehdr), 0);
 	if (ret != KDUMP_OK)
 		return set_error(ctx, ret, "Cannot read dump header");
 
--- a/src/kdumpfile/flatmap.c
+++ b/src/kdumpfile/flatmap.c
@@ -231,8 +231,8 @@ flatmap_free(struct flattened_map *map)
  * at position @p pos after rearrangement.
  */
 kdump_status
-flatmap_pread(struct flattened_map *map, void *buf, size_t len,
-	      off_t pos)
+flatmap_pread_flat(struct flattened_map *map, void *buf, size_t len,
+		   off_t pos)
 {
 	struct flattened_file_map *fmap = &map->fmap;
 	const addrxlat_range_t *range, *end;
@@ -283,8 +283,8 @@ flatmap_pread(struct flattened_map *map,
  * Get a contiguous data chunk from a flattened dump file.
  */
 kdump_status
-flatmap_get_chunk(struct flattened_map *map, struct fcache_chunk *fch,
-		  size_t len, off_t pos)
+flatmap_get_chunk_flat(struct flattened_map *map, struct fcache_chunk *fch,
+		       size_t len, off_t pos)
 {
 	struct flattened_file_map *fmap = &map->fmap;
 	const addrxlat_range_t *range, *end;
--- a/src/kdumpfile/kdumpfile-priv.h
+++ b/src/kdumpfile/kdumpfile-priv.h
@@ -1531,10 +1531,10 @@ INTERNAL_DECL(kdump_status, flatmap_init
 	      (struct flattened_map *map, kdump_ctx_t *ctx));
 INTERNAL_DECL(void, flatmap_free,
 	      (struct flattened_map *map));
-INTERNAL_DECL(kdump_status, flatmap_pread,
+INTERNAL_DECL(kdump_status, flatmap_pread_flat,
 	      (struct flattened_map *map, void *buf, size_t len,
 	       off_t pos));
-INTERNAL_DECL(kdump_status, flatmap_get_chunk,
+INTERNAL_DECL(kdump_status, flatmap_get_chunk_flat,
 	      (struct flattened_map *map, struct fcache_chunk *fch,
 	       size_t len, off_t pos));
 
@@ -1548,6 +1548,45 @@ flatmap_isflattened(struct flattened_map
 	return map->fmap.map;
 }
 
+/** Read buffer from a possibly flattened 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
+flatmap_pread(struct flattened_map *flatmap, void *buf, size_t len,
+	      off_t pos)
+{
+	return flatmap_isflattened(flatmap)
+		? flatmap_pread_flat(flatmap, buf, len, pos)
+		: fcache_pread(flatmap->fcache, buf, len, pos);
+}
+
+/** Get a contiguous data chunk from a possibly flattend 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
+flatmap_get_chunk(struct flattened_map *flatmap, struct fcache_chunk *fch,
+		  size_t len, off_t pos)
+{
+	return flatmap_isflattened(flatmap)
+		? flatmap_get_chunk_flat(flatmap, fch, len, pos)
+		: fcache_get_chunk(flatmap->fcache, fch, len, pos);
+}
+
+
 /** Check if a character is a POSIX white space.
  * @param c  Character to check.
  *
openSUSE Build Service is sponsored by