1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-31 14:50:15 +03:00

coredump: use _cleanup_ pattern

Note that c.f needs to be closed _before_ taking or freeing
the buf pointer, as it might be invalidated
This commit is contained in:
Luca Boccassi 2021-11-29 11:31:00 +00:00
parent fe165e70cd
commit 67f7675f47

View File

@ -21,7 +21,7 @@
#define THREADS_MAX 64
#define ELF_PACKAGE_METADATA_ID 0xcafe1a7e
struct stack_context {
typedef struct StackContext {
FILE *f;
Dwfl *dwfl;
Elf *elf;
@ -29,10 +29,31 @@ struct stack_context {
unsigned n_frame;
JsonVariant **package_metadata;
Set **modules;
};
} StackContext;
static StackContext* stack_context_destroy(StackContext *c) {
if (!c)
return NULL;
c->f = safe_fclose(c->f);
if (c->dwfl) {
dwfl_end(c->dwfl);
c->dwfl = NULL;
}
if (c->elf) {
elf_end(c->elf);
c->elf = NULL;
}
return NULL;
}
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(Elf *, elf_end, NULL);
static int frame_callback(Dwfl_Frame *frame, void *userdata) {
struct stack_context *c = userdata;
StackContext *c = userdata;
Dwarf_Addr pc, pc_adjusted, bias = 0;
_cleanup_free_ Dwarf_Die *scopes = NULL;
const char *fname = NULL, *symbol = NULL;
@ -93,7 +114,7 @@ static int frame_callback(Dwfl_Frame *frame, void *userdata) {
}
static int thread_callback(Dwfl_Thread *thread, void *userdata) {
struct stack_context *c = userdata;
StackContext *c = userdata;
pid_t tid;
assert(thread);
@ -118,7 +139,7 @@ static int thread_callback(Dwfl_Thread *thread, void *userdata) {
return DWARF_CB_OK;
}
static int parse_package_metadata(const char *name, JsonVariant *id_json, Elf *elf, struct stack_context *c) {
static int parse_package_metadata(const char *name, JsonVariant *id_json, Elf *elf, StackContext *c) {
size_t n_program_headers;
int r;
@ -215,7 +236,7 @@ static int parse_package_metadata(const char *name, JsonVariant *id_json, Elf *e
static int module_callback(Dwfl_Module *mod, void **userdata, const char *name, Dwarf_Addr start, void *arg) {
_cleanup_(json_variant_unrefp) JsonVariant *id_json = NULL;
struct stack_context *c = arg;
StackContext *c = arg;
size_t n_program_headers;
GElf_Addr id_vaddr, bias;
const unsigned char *id;
@ -299,7 +320,7 @@ static int module_callback(Dwfl_Module *mod, void **userdata, const char *name,
if (!data)
continue;
Elf *memelf = elf_memory(data->d_buf, data->d_size);
_cleanup_(elf_endp) Elf *memelf = elf_memory(data->d_buf, data->d_size);
if (!memelf)
continue;
r = parse_package_metadata(name, id_json, memelf, c);
@ -322,11 +343,11 @@ static int parse_core(int fd, const char *executable, char **ret, JsonVariant **
_cleanup_(json_variant_unrefp) JsonVariant *package_metadata = NULL;
_cleanup_(set_freep) Set *modules = NULL;
struct stack_context c = {
_cleanup_free_ char *buf = NULL; /* buf should be freed last, c.f closed first (via stack_context_destroy) */
_cleanup_(stack_context_destroy) StackContext c = {
.package_metadata = &package_metadata,
.modules = &modules,
};
_cleanup_free_ char *buf = NULL;
size_t sz = 0;
int r;
@ -343,63 +364,38 @@ static int parse_core(int fd, const char *executable, char **ret, JsonVariant **
elf_version(EV_CURRENT);
c.elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
if (!c.elf) {
r = -EINVAL;
goto finish;
}
if (!c.elf)
return -EINVAL;
c.dwfl = dwfl_begin(&callbacks);
if (!c.dwfl) {
r = -EINVAL;
goto finish;
}
if (!c.dwfl)
return -EINVAL;
if (dwfl_core_file_report(c.dwfl, c.elf, executable) < 0) {
r = -EINVAL;
goto finish;
}
if (dwfl_core_file_report(c.dwfl, c.elf, executable) < 0)
return -EINVAL;
if (dwfl_report_end(c.dwfl, NULL, NULL) != 0) {
r = -EINVAL;
goto finish;
}
if (dwfl_report_end(c.dwfl, NULL, NULL) != 0)
return -EINVAL;
if (dwfl_getmodules(c.dwfl, &module_callback, &c, 0) < 0) {
r = -EINVAL;
goto finish;
}
if (dwfl_getmodules(c.dwfl, &module_callback, &c, 0) < 0)
return -EINVAL;
if (dwfl_core_file_attach(c.dwfl, c.elf) < 0) {
r = -EINVAL;
goto finish;
}
if (dwfl_core_file_attach(c.dwfl, c.elf) < 0)
return -EINVAL;
if (dwfl_getthreads(c.dwfl, thread_callback, &c) < 0) {
r = -EINVAL;
goto finish;
}
if (dwfl_getthreads(c.dwfl, thread_callback, &c) < 0)
return -EINVAL;
r = fflush_and_check(c.f);
if (r < 0)
goto finish;
c.f = safe_fclose(c.f);
return r;
c.f = safe_fclose(c.f);
*ret = TAKE_PTR(buf);
if (ret_package_metadata)
*ret_package_metadata = TAKE_PTR(package_metadata);
r = 0;
finish:
if (c.dwfl)
dwfl_end(c.dwfl);
if (c.elf)
elf_end(c.elf);
safe_fclose(c.f);
return r;
return 0;
}
void coredump_parse_core(int fd, const char *executable, char **ret, JsonVariant **ret_package_metadata) {