summaryrefslogtreecommitdiff
path: root/src/coredump
diff options
context:
space:
mode:
authorLuca Boccassi <luca.boccassi@microsoft.com>2021-11-29 11:31:00 +0000
committerLuca Boccassi <luca.boccassi@microsoft.com>2021-11-30 16:49:58 +0000
commit67f7675f477d369506eeb17ef2d5b365f83ac84a (patch)
tree43411a5924265b8f12cb81672a81f304a3018349 /src/coredump
parentfe165e70cd787806fe0809efc2db45ff0451d645 (diff)
downloadsystemd-67f7675f477d369506eeb17ef2d5b365f83ac84a.tar.gz
coredump: use _cleanup_ pattern
Note that c.f needs to be closed _before_ taking or freeing the buf pointer, as it might be invalidated
Diffstat (limited to 'src/coredump')
-rw-r--r--src/coredump/stacktrace.c98
1 files changed, 47 insertions, 51 deletions
diff --git a/src/coredump/stacktrace.c b/src/coredump/stacktrace.c
index a74ef41ac9..23161d5ac1 100644
--- a/src/coredump/stacktrace.c
+++ b/src/coredump/stacktrace.c
@@ -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) {