static int fileline_initialize (struct backtrace_state *state, backtrace_error_callback error_callback, void *data) { int failed; fileline fileline_fn; int pass; if (!state->threaded) failed = state->fileline_initialization_failed; else failed = backtrace_atomic_load_int (&state->fileline_initialization_failed); if (failed) { error_callback (data, "failed to read executable information", -1); return 0; } if (!state->threaded) fileline_fn = state->fileline_fn; else fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn); if (fileline_fn != NULL) return 1; /* We have not initialized the information. Do it now. */ const char *filename; for (pass = 0; pass < 4; ++pass) { switch (pass) { case 0: filename = state->filename; break; case 1: filename = getexecname (); break; case 2: filename = "/proc/self/exe"; break; case 3: filename = "/proc/curproc/file"; break; default: abort (); } /* If we've got a filename and the file exists, break. */ if (filename && filename[0] && (access(filename, F_OK) == 0)) break; filename = NULL; } if (!filename) { if (state->filename != NULL) error_callback (data, state->filename, ENOENT); else error_callback (data, "libbacktrace could not find executable to open", 0); failed = 1; } if (!failed) { if (!backtrace_initialize (state, filename, 0, 1, error_callback, data, &fileline_fn)) failed = 1; } if (failed) { if (!state->threaded) state->fileline_initialization_failed = 1; else backtrace_atomic_store_int (&state->fileline_initialization_failed, 1); return 0; } if (!state->threaded) state->fileline_fn = fileline_fn; else { backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn); /* Note that if two threads initialize at once, one of the data sets may be leaked. */ } return 1; }
static int fileline_initialize (struct backtrace_state *state, backtrace_error_callback error_callback, void *data) { int failed; fileline fileline_fn; int pass; int called_error_callback; int descriptor; if (!state->threaded) failed = state->fileline_initialization_failed; else failed = backtrace_atomic_load_int (&state->fileline_initialization_failed); if (failed) { error_callback (data, "failed to read executable information", -1); return 0; } if (!state->threaded) fileline_fn = state->fileline_fn; else fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn); if (fileline_fn != NULL) return 1; /* We have not initialized the information. Do it now. */ descriptor = -1; called_error_callback = 0; for (pass = 0; pass < 4; ++pass) { const char *filename; int does_not_exist; switch (pass) { case 0: filename = state->filename; break; case 1: filename = getexecname (); break; case 2: filename = "/proc/self/exe"; break; case 3: filename = "/proc/curproc/file"; break; default: abort (); } if (filename == NULL) continue; descriptor = backtrace_open (filename, error_callback, data, &does_not_exist); if (descriptor < 0 && !does_not_exist) { called_error_callback = 1; break; } if (descriptor >= 0) break; } if (descriptor < 0) { if (!called_error_callback) { if (state->filename != NULL) error_callback (data, state->filename, ENOENT); else error_callback (data, "libbacktrace could not find executable to open", 0); } failed = 1; } if (!failed) { if (!backtrace_initialize (state, descriptor, error_callback, data, &fileline_fn)) failed = 1; } if (failed) { if (!state->threaded) state->fileline_initialization_failed = 1; else backtrace_atomic_store_int (&state->fileline_initialization_failed, 1); return 0; } if (!state->threaded) state->fileline_fn = fileline_fn; else { backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn); /* Note that if two threads initialize at once, one of the data sets may be leaked. */ } return 1; }
int backtrace_fileline_initialize (struct backtrace_state *state, uintptr_t base_address, int is_exe, backtrace_error_callback error_callback, void *data) { int failed; fileline fileline_fn; if (!state->threaded) failed = state->fileline_initialization_failed; else failed = backtrace_atomic_load_int (&state->fileline_initialization_failed); if (failed) { error_callback (data, "failed to read executable information", -1); return 0; } if (!state->threaded) fileline_fn = state->fileline_fn; else fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn); if (fileline_fn != NULL) return 1; /* We have not initialized information. Do it now. */ /* For this function, we need a filename and base address. */ if (!state->filename || !base_address) { error_callback (data, state->filename, ENOENT); failed = 1; } else { if (!backtrace_initialize (state, state->filename, base_address, is_exe, error_callback, data, &fileline_fn)) failed = 1; } if (failed) { if (!state->threaded) state->fileline_initialization_failed = 1; else backtrace_atomic_store_int (&state->fileline_initialization_failed, 1); return 0; } if (!state->threaded) state->fileline_fn = fileline_fn; else { backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn); /* Note that if two threads initialize at once, one of the data sets may be leaked. */ } return 1; }