mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zdump: Extract dfo_mem_chunk interface from DFO
The primary goal is to separate DFO code into multiple smaller modules and make it unit testable. This refactoring only moved the code around w/o changing any functionality. Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
f6a7da141c
commit
4bd16ba8ea
@@ -47,7 +47,7 @@ OBJECTS = zgetdump.o opts.o zg.o \
|
|||||||
dfi_s390.o dfi_s390_ext.o\
|
dfi_s390.o dfi_s390_ext.o\
|
||||||
dfi_s390mv.o dfi_s390mv_ext.o \
|
dfi_s390mv.o dfi_s390mv_ext.o \
|
||||||
dfi_s390tape.o dfi_kdump.o \
|
dfi_s390tape.o dfi_kdump.o \
|
||||||
dfi_devmem.o dfo.o \
|
dfi_devmem.o dfo.o dfo_mem_chunk.o \
|
||||||
dfo_elf.o dfo_s390.o \
|
dfo_elf.o dfo_s390.o \
|
||||||
df_s390.o \
|
df_s390.o \
|
||||||
dt.o dt_s390sv.o dt_s390sv_ext.o \
|
dt.o dt_s390sv.o dt_s390sv_ext.o \
|
||||||
|
|||||||
119
zdump/dfo.c
119
zdump/dfo.c
@@ -9,16 +9,13 @@
|
|||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <time.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "lib/util_list.h"
|
#include "zg.h"
|
||||||
|
#include "dfo_mem_chunk.h"
|
||||||
#include "dfi_mem_chunk.h"
|
|
||||||
#include "dfo.h"
|
#include "dfo.h"
|
||||||
|
|
||||||
#define dfo_chunk_iterate(dfo_chunk) \
|
|
||||||
util_list_iterate(&l.dump.chunk_list, dfo_chunk)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DFO vector
|
* DFO vector
|
||||||
*/
|
*/
|
||||||
@@ -28,70 +25,14 @@ static struct dfo *dfo_vec[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Dump (output) information
|
|
||||||
*/
|
|
||||||
struct dump {
|
|
||||||
u64 off; /* Current file offset in dump */
|
|
||||||
u64 size; /* Size of dump in bytes */
|
|
||||||
unsigned int chunk_cnt; /* Number of dump chunks */
|
|
||||||
struct util_list chunk_list; /* DFO chunk list */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File local static data
|
* File local static data
|
||||||
*/
|
*/
|
||||||
static struct {
|
static struct {
|
||||||
struct dump dump;
|
u64 off; /* Current file offset in dump */
|
||||||
struct dfo *dfo;
|
struct dfo *dfo;
|
||||||
} l;
|
} l;
|
||||||
|
|
||||||
/*
|
|
||||||
* Add dump chunk
|
|
||||||
*/
|
|
||||||
void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn)
|
|
||||||
{
|
|
||||||
struct dfo_chunk *dfo_chunk;
|
|
||||||
|
|
||||||
dfo_chunk = zg_alloc(sizeof(*dfo_chunk));
|
|
||||||
dfo_chunk->start = start;
|
|
||||||
dfo_chunk->end = start + size - 1;
|
|
||||||
dfo_chunk->data = data;
|
|
||||||
dfo_chunk->read_fn = read_fn;
|
|
||||||
util_list_add_head(&l.dump.chunk_list, dfo_chunk);
|
|
||||||
l.dump.chunk_cnt++;
|
|
||||||
l.dump.size = MAX(l.dump.size, dfo_chunk->end + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dump chunk function: Copy zero pages for chunk
|
|
||||||
*/
|
|
||||||
void dfo_chunk_zero_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
|
|
||||||
{
|
|
||||||
(void) dfo_chunk;
|
|
||||||
(void) off;
|
|
||||||
|
|
||||||
memset(buf, 0, cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dump chunk function: Copy given buffer for chunk
|
|
||||||
*/
|
|
||||||
void dfo_chunk_buf_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
|
|
||||||
{
|
|
||||||
memcpy(buf, dfo_chunk->data + off, cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dump chunk function: Copy given memory range for chunk
|
|
||||||
*/
|
|
||||||
void dfo_chunk_mem_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
|
|
||||||
{
|
|
||||||
struct dfi_mem_chunk *mem_chunk = dfo_chunk->data;
|
|
||||||
|
|
||||||
mem_chunk->read_fn(mem_chunk, off, buf, cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get DFO name
|
* Get DFO name
|
||||||
*/
|
*/
|
||||||
@@ -125,55 +66,17 @@ void dfo_init(void)
|
|||||||
{
|
{
|
||||||
if (!l.dfo)
|
if (!l.dfo)
|
||||||
ABORT("DFO not set");
|
ABORT("DFO not set");
|
||||||
util_list_init(&l.dump.chunk_list, struct dfo_chunk, list);
|
if (dfo_chunk_init())
|
||||||
|
ABORT("DFO memory chunk init failed");
|
||||||
l.dfo->init();
|
l.dfo->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Find dump chunk for offset "off"
|
|
||||||
*
|
|
||||||
* This function is a bit hacky. DFO chunks can overlap. If two DFO chunks
|
|
||||||
* overlap, the last registered chunk wins. The dfo_chunk_find() function
|
|
||||||
* reflects that by returning the first memory chunk that is found in
|
|
||||||
* the dfo chunk list.
|
|
||||||
*
|
|
||||||
* In addition to that it calculates the "virtual end" of that chunk. An
|
|
||||||
* overlapping chunk can limit the "virtual end" of an underlying chunk so
|
|
||||||
* that the "virtual end" of that chunk is lower than the "real end".
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
|
||||||
* chunk 1.: |------|
|
|
||||||
* chunk 2.: |---------------------|
|
|
||||||
* off.....: ^
|
|
||||||
* virt end: ^
|
|
||||||
* real end: ^
|
|
||||||
*
|
|
||||||
* In this case chunk 2 will be returned and "end" is set to the start of
|
|
||||||
* chunk 1.
|
|
||||||
*/
|
|
||||||
static struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end)
|
|
||||||
{
|
|
||||||
struct dfo_chunk *dfo_chunk;
|
|
||||||
|
|
||||||
*end = U64_MAX;
|
|
||||||
dfo_chunk_iterate(dfo_chunk) {
|
|
||||||
if (dfo_chunk->start <= off && dfo_chunk->end >= off) {
|
|
||||||
*end = MIN(*end, dfo_chunk->end);
|
|
||||||
return dfo_chunk;
|
|
||||||
} else if (dfo_chunk->start > off) {
|
|
||||||
*end = MIN(*end, dfo_chunk->start - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Seek to output dump offset "off"
|
* Seek to output dump offset "off"
|
||||||
*/
|
*/
|
||||||
void dfo_seek(u64 off)
|
void dfo_seek(u64 off)
|
||||||
{
|
{
|
||||||
l.dump.off = off;
|
l.off = off;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -183,7 +86,7 @@ u64 dfo_read(void *buf, u64 cnt)
|
|||||||
{
|
{
|
||||||
struct dfo_chunk *dfo_chunk;
|
struct dfo_chunk *dfo_chunk;
|
||||||
u64 copied = 0, end, size;
|
u64 copied = 0, end, size;
|
||||||
u64 off = l.dump.off;
|
u64 off = l.off;
|
||||||
|
|
||||||
while (copied != cnt) {
|
while (copied != cnt) {
|
||||||
dfo_chunk = dfo_chunk_find(off, &end);
|
dfo_chunk = dfo_chunk_find(off, &end);
|
||||||
@@ -196,7 +99,7 @@ u64 dfo_read(void *buf, u64 cnt)
|
|||||||
off += size;
|
off += size;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
l.dump.off = off;
|
l.off = off;
|
||||||
return copied;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,5 +108,5 @@ out:
|
|||||||
*/
|
*/
|
||||||
u64 dfo_size(void)
|
u64 dfo_size(void)
|
||||||
{
|
{
|
||||||
return l.dump.size;
|
return dfo_chunk_dump_size();
|
||||||
}
|
}
|
||||||
|
|||||||
37
zdump/dfo.h
37
zdump/dfo.h
@@ -12,37 +12,12 @@
|
|||||||
#ifndef DFO_H
|
#ifndef DFO_H
|
||||||
#define DFO_H
|
#define DFO_H
|
||||||
|
|
||||||
#include "lib/util_list.h"
|
u64 dfo_read(void *buf, u64 cnt);
|
||||||
#include "zg.h"
|
void dfo_seek(u64 addr);
|
||||||
|
u64 dfo_size(void);
|
||||||
struct dfo_chunk;
|
const char *dfo_name(void);
|
||||||
|
void dfo_init(void);
|
||||||
typedef void (*dfo_chunk_read_fn)(struct dfo_chunk *chunk, u64 off,
|
int dfo_set(const char *dfo_name);
|
||||||
void *buf, u64 cnt);
|
|
||||||
|
|
||||||
struct dfo_chunk {
|
|
||||||
struct util_list_node list;
|
|
||||||
u64 start;
|
|
||||||
u64 end;
|
|
||||||
dfo_chunk_read_fn read_fn;
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void dfo_chunk_zero_fn(struct dfo_chunk *chunk, u64 off, void *buf,
|
|
||||||
u64 cnt);
|
|
||||||
extern void dfo_chunk_buf_fn(struct dfo_chunk *chunk, u64 off, void *buf,
|
|
||||||
u64 cnt);
|
|
||||||
extern void dfo_chunk_mem_fn(struct dfo_chunk *chunk, u64 off, void *buf,
|
|
||||||
u64 cnt);
|
|
||||||
extern void dfo_chunk_add(u64 start, u64 size, void *data,
|
|
||||||
dfo_chunk_read_fn read_fn);
|
|
||||||
|
|
||||||
extern u64 dfo_read(void *buf, u64 cnt);
|
|
||||||
extern void dfo_seek(u64 addr);
|
|
||||||
extern u64 dfo_size(void);
|
|
||||||
extern const char *dfo_name(void);
|
|
||||||
extern void dfo_init(void);
|
|
||||||
extern int dfo_set(const char *dfo_name);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DFO operations
|
* DFO operations
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "df_elf.h"
|
#include "df_elf.h"
|
||||||
#include "dfi.h"
|
#include "dfi.h"
|
||||||
#include "dfi_mem_chunk.h"
|
#include "dfi_mem_chunk.h"
|
||||||
|
#include "dfo_mem_chunk.h"
|
||||||
#include "dfi_vmcoreinfo.h"
|
#include "dfi_vmcoreinfo.h"
|
||||||
#include "dfo.h"
|
#include "dfo.h"
|
||||||
|
|
||||||
|
|||||||
128
zdump/dfo_mem_chunk.c
Normal file
128
zdump/dfo_mem_chunk.c
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright IBM Corp. 2001, 2017, 2021
|
||||||
|
*
|
||||||
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "zg.h"
|
||||||
|
#include "dfi_mem_chunk.h"
|
||||||
|
#include "dfo_mem_chunk.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File local static data
|
||||||
|
*/
|
||||||
|
static struct {
|
||||||
|
u64 size; /* Size of dump in bytes */
|
||||||
|
unsigned int chunk_cnt; /* Number of dump chunks */
|
||||||
|
struct util_list chunk_list; /* DFO chunk list */
|
||||||
|
} l;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add dump chunk
|
||||||
|
*/
|
||||||
|
void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn)
|
||||||
|
{
|
||||||
|
struct dfo_chunk *dfo_chunk;
|
||||||
|
|
||||||
|
dfo_chunk = zg_alloc(sizeof(*dfo_chunk));
|
||||||
|
dfo_chunk->start = start;
|
||||||
|
dfo_chunk->end = start + size - 1;
|
||||||
|
dfo_chunk->data = data;
|
||||||
|
dfo_chunk->read_fn = read_fn;
|
||||||
|
util_list_add_head(&l.chunk_list, dfo_chunk);
|
||||||
|
l.chunk_cnt++;
|
||||||
|
l.size = MAX(l.size, dfo_chunk->end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump chunk function: Copy zero pages for chunk
|
||||||
|
*/
|
||||||
|
void dfo_chunk_zero_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
|
||||||
|
{
|
||||||
|
(void) dfo_chunk;
|
||||||
|
(void) off;
|
||||||
|
|
||||||
|
memset(buf, 0, cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump chunk function: Copy given buffer for chunk
|
||||||
|
*/
|
||||||
|
void dfo_chunk_buf_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
|
||||||
|
{
|
||||||
|
memcpy(buf, dfo_chunk->data + off, cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump chunk function: Copy given memory range for chunk
|
||||||
|
*/
|
||||||
|
void dfo_chunk_mem_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
|
||||||
|
{
|
||||||
|
struct dfi_mem_chunk *mem_chunk = dfo_chunk->data;
|
||||||
|
|
||||||
|
mem_chunk->read_fn(mem_chunk, off, buf, cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find dump chunk for offset "off"
|
||||||
|
*
|
||||||
|
* This function is a bit hacky. DFO chunks can overlap. If two DFO chunks
|
||||||
|
* overlap, the last registered chunk wins. The dfo_chunk_find() function
|
||||||
|
* reflects that by returning the first memory chunk that is found in
|
||||||
|
* the dfo chunk list.
|
||||||
|
*
|
||||||
|
* In addition to that it calculates the "virtual end" of that chunk. An
|
||||||
|
* overlapping chunk can limit the "virtual end" of an underlying chunk so
|
||||||
|
* that the "virtual end" of that chunk is lower than the "real end".
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* chunk 1.: |------|
|
||||||
|
* chunk 2.: |---------------------|
|
||||||
|
* off.....: ^
|
||||||
|
* virt end: ^
|
||||||
|
* real end: ^
|
||||||
|
*
|
||||||
|
* In this case chunk 2 will be returned and "end" is set to the start of
|
||||||
|
* chunk 1.
|
||||||
|
*/
|
||||||
|
struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end)
|
||||||
|
{
|
||||||
|
struct dfo_chunk *dfo_chunk;
|
||||||
|
|
||||||
|
*end = U64_MAX;
|
||||||
|
dfo_chunk_iterate(dfo_chunk) {
|
||||||
|
if (dfo_chunk->start <= off && dfo_chunk->end >= off) {
|
||||||
|
*end = MIN(*end, dfo_chunk->end);
|
||||||
|
return dfo_chunk;
|
||||||
|
} else if (dfo_chunk->start > off) {
|
||||||
|
*end = MIN(*end, dfo_chunk->start - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct util_list *dfo_chunk_list(void)
|
||||||
|
{
|
||||||
|
return &l.chunk_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 dfo_chunk_dump_size(void)
|
||||||
|
{
|
||||||
|
return l.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dfo_chunk_init(void)
|
||||||
|
{
|
||||||
|
util_list_init(&l.chunk_list, struct dfo_chunk, list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dfo_chunk_deinit(void)
|
||||||
|
{
|
||||||
|
memset(&l, 0, sizeof(l));
|
||||||
|
}
|
||||||
42
zdump/dfo_mem_chunk.h
Normal file
42
zdump/dfo_mem_chunk.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright IBM Corp. 2001, 2017, 2021
|
||||||
|
*
|
||||||
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DFO_MEM_CHUNK_H
|
||||||
|
#define DFO_MEM_CHUNK_H
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
#include "lib/util_list.h"
|
||||||
|
|
||||||
|
struct dfo_chunk;
|
||||||
|
|
||||||
|
typedef void (*dfo_chunk_read_fn)(struct dfo_chunk *chunk, u64 off,
|
||||||
|
void *buf, u64 cnt);
|
||||||
|
|
||||||
|
struct dfo_chunk {
|
||||||
|
struct util_list_node list;
|
||||||
|
u64 start;
|
||||||
|
u64 end;
|
||||||
|
dfo_chunk_read_fn read_fn;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
void dfo_chunk_zero_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt);
|
||||||
|
void dfo_chunk_buf_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt);
|
||||||
|
void dfo_chunk_mem_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt);
|
||||||
|
void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn);
|
||||||
|
struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end);
|
||||||
|
|
||||||
|
struct util_list *dfo_chunk_list(void);
|
||||||
|
#define dfo_chunk_iterate(dfo_chunk) \
|
||||||
|
util_list_iterate(dfo_chunk_list(), dfo_chunk)
|
||||||
|
|
||||||
|
u64 dfo_chunk_dump_size(void);
|
||||||
|
|
||||||
|
int dfo_chunk_init(void);
|
||||||
|
void dfo_chunk_deinit(void);
|
||||||
|
|
||||||
|
#endif /* DFO_MEM_CHUNK_H */
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "df_s390.h"
|
#include "df_s390.h"
|
||||||
#include "dfi_mem_chunk.h"
|
#include "dfi_mem_chunk.h"
|
||||||
|
#include "dfo_mem_chunk.h"
|
||||||
#include "dfo.h"
|
#include "dfo.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user