- register int i;
-
-# if NFRAMES == 1
- GC_err_printf0("\tCaller at allocation:\n");
-# else
- GC_err_printf0("\tCall chain at allocation:\n");
-# endif
- for (i = 0; i < NFRAMES; i++) {
- if (info[i].ci_pc == 0) break;
-# if NARGS > 0
- {
- int j;
-
- GC_err_printf0("\t\targs: ");
- for (j = 0; j < NARGS; j++) {
- if (j != 0) GC_err_printf0(", ");
- GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]),
- ~(info[i].ci_arg[j]));
- }
- GC_err_printf0("\n");
- }
-# endif
-# if defined(HAVE_BUILTIN_BACKTRACE) && !defined(REDIRECT_MALLOC)
- /* Unfortunately backtrace_symbols calls malloc, which makes */
- /* it dangersous if that has been redirected. */
- {
- char **sym_name =
- backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
- char *name = sym_name[0];
- GC_bool found_it = (strchr(name, '(') != 0);
- FILE *pipe;
-# ifdef LINUX
- if (!found_it) {
-# define EXE_SZ 100
- static char exe_name[EXE_SZ];
-# define CMD_SZ 200
- char cmd_buf[CMD_SZ];
-# define RESULT_SZ 200
- static char result_buf[RESULT_SZ];
- size_t result_len;
- static GC_bool found_exe_name = FALSE;
- static GC_bool will_fail = FALSE;
- int ret_code;
- /* Unfortunately, this is the common case for the */
- /* main executable. */
- /* Try to get it via a hairy and expensive scheme. */
- /* First we get the name of the executable: */
- if (will_fail) goto out;
- if (!found_exe_name) {
- ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
- if (ret_code < 0 || ret_code >= EXE_SZ || exe_name[0] != '/') {
- will_fail = TRUE; /* Dont try again. */
- goto out;
- }
- exe_name[ret_code] = '\0';
- found_exe_name = TRUE;
- }
- /* Then we use popen to start addr2line -e <exe> <addr> */
- /* There are faster ways to do this, but hopefully this */
- /* isn't time critical. */
- sprintf(cmd_buf, "/usr/bin/addr2line -e %s 0x%lx", exe_name,
- (unsigned long)info[i].ci_pc);
- pipe = popen(cmd_buf, "r");
- if (pipe < 0 || fgets(result_buf, RESULT_SZ, pipe) == 0) {
- will_fail = TRUE;
- goto out;
- }
- result_len = strlen(result_buf);
- if (result_buf[result_len - 1] == '\n') --result_len;
- if (result_buf[0] == '?'
- || result_buf[result_len-2] == ':'
- && result_buf[result_len-1] == '0')
- goto out;
- if (result_len < RESULT_SZ - 25) {
- /* Add in hex address */
- sprintf(result_buf + result_len, " [0x%lx]",
- (unsigned long)info[i].ci_pc);
- }
- name = result_buf;
- pclose(pipe);
- out:
- }
-# endif
- GC_err_printf1("\t\t%s\n", name);
- free(sym_name);
- }
-# else
- GC_err_printf1("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
-# endif
- }