17 #include <sys/types.h> 27 #define system(cmd) (-1) 30 #define PRETOSTR(x) #x 31 #define TOSTR(x) PRETOSTR(x) 33 #if defined(SUN4) && !defined(PSTACKTRACE) 34 #define PSTACKTRACE /bin/pstack 37 #define strequ(s1,s2) ((void *)s1 && (void *)s2 && strcmp(s1,s2) == 0) 38 #define strnequ(s1,s2,n) ((void *)s1 && (void *)s2 && memcmp(s1,s2,n) == 0) 46 static int ResolveViaBFD(
void *address, BFD_t *b,
const char *str);
49 #if (defined(LINUX) || defined(SUN4)) && !defined(XT3) && !defined(XD1) 55 #define FFL __FUNCTION__,__FILE__,__LINE__ 62 #include <sys/resource.h> 64 #if defined(LINUX) && !defined(CYGWIN) && !defined(DARWIN) && !defined(CRAYXT) 70 #define HANDLE pthread_t * 82 #if !defined(ADDR2LINE) 83 #define ADDR2LINE /usr/bin/addr2line 86 #define GNUC_BTRACE 128 87 #define len_addr2linecmd (sizeof(TOSTR(ADDR2LINE)) + 80 + 4096 + GNUC_BTRACE * 30) 102 #if defined(__GNUC__) 103 #include <sys/syscall.h> 107 #define SYS_gettid __NR_gettid 111 pid_t tid = syscall(SYS_gettid);
119 size_t StackSize = 0;
121 long long int value = 0;
122 char *env_ignore = getenv(
"IGNORE_STACKSIZE");
125 char *envstksz = getenv(
"STACKSIZE");
126 char *envompstksz = getenv(
"OMP_STACKSIZE");
127 char *envmult = getenv(
"STACKMULT");
131 char *env_procid = getenv(
"EC_FARM_ID");
132 if (!env_procid) env_procid = getenv(
"ALPS_APP_PE");
133 if (!env_procid) env_procid = getenv(
"PMI_RANK");
134 if (!env_procid) env_procid = getenv(
"OMPI_COMM_WORLD_RANK");
137 me = atoi(env_procid);
138 if (me == 0) display = 1;
141 if (env_ignore) ignore = atoi(env_ignore);
142 if (!envstksz && !envompstksz) ignore = 1;
144 if (envstksz || envompstksz) {
146 char *s = envstksz ? strdup(envstksz) : strdup(envompstksz);
147 int slen = strlen(s);
148 char *last = s + slen - 1;
149 long long int mult = 1024;
150 if (*last ==
'b' || *last ==
'B') {
154 else if (*last ==
'k' || *last ==
'K') {
158 else if (*last ==
'm' || *last ==
'M') {
162 else if (*last ==
'g' || *last ==
'G') {
166 value = atoll(s) * mult;
169 StackMult = atoi(envmult);
170 if (StackMult < 1) StackMult = 1;
172 if (envstksz) StackMult = 1;
173 if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
174 rlim.rlim_cur = value * StackMult;
175 setrlimit(RLIMIT_STACK, &rlim);
180 pthread_attr_t Attributes;
182 pid_t
pid = getpid();
184 char hostname[HOST_NAME_MAX];
185 char prefix[HOST_NAME_MAX + 256];
186 if (gethostname(hostname,
sizeof(hostname)) != 0) strcpy(hostname,
"unknown");
188 snprintf(prefix,
sizeof(prefix),
"%s:%d:%lld:%lld",hostname,me,(
long long int)pid,(
long long int)tid);
191 memset(&Attributes, 0x0,
sizeof (Attributes));
192 pthread_getattr_np(pthread_self(), &Attributes);
193 pthread_attr_getstack(&Attributes, &StackAddress, &StackSize);
194 pthread_attr_destroy(&Attributes);
198 "[%s] [%s@%s:%d] : Master thread's stack size = %llu bytes [setrlimit() was not called]\n",
200 (
unsigned long long int)StackSize);
204 "[%s] [%s@%s:%d] : Master thread's stack size = %llu bytes, (export STACKSIZE=%lld bytes)\n",
206 (
unsigned long long int)StackSize,
209 else if (envompstksz) {
211 "[%s] [%s@%s:%d] : Master thread's stack size = %llu bytes, (export OMP_STACKSIZE=%lld bytes for slave thread, STACKMULT = %d)\n",
213 (
unsigned long long int)StackSize,
226 const char *pfx = prefix ? prefix :
"";
227 const char *ts = timestr ? timestr :
"";
228 int sigcontextptr_given = sigcontextptr ? 1 : 0;
231 #if defined(__GNUC__) && defined(LINUX) && !defined(CYGWIN) 234 static int recur = 0;
236 #if defined(__GNUC__) && defined(LINUX) && !defined(CYGWIN) && !defined(DARWIN) 237 if (!sigcontextptr) {
238 sigcontextptr = (getcontext(&ctx) == 0) ? &ctx : NULL;
241 fprintf(stderr,
"%s %s [%s@%s:%d] Backtrace(s) for program '%s' : sigcontextptr=%p\n",
242 pfx,ts,FFL,a_out ? a_out :
"/dev/null", sigcontextptr);
246 "%s %s [%s@%s:%d] I don't handle recursive calls very well (recursion level = %d)\n",
249 fprintf(stderr,
"%s %s [%s@%s:%d] Recursion too deep. Exiting immediately with _exit(%d)\n",
256 #if defined(__GNUC__) && defined(LINUX) && !defined(CYGWIN) && !defined(DARWIN) 263 void *trace[GNUC_BTRACE];
264 ucontext_t *uc = (ucontext_t *)sigcontextptr;
265 int fd = fileno(stderr);
266 int trace_size = backtrace(trace, GNUC_BTRACE);
268 char **strings = NULL;
269 if (trace_size > 0) {
272 trace[1] = (
void *) uc->uc_mcontext.gregs[REG_RIP];
273 #elif defined(REG_EIP)
274 trace[1] = (
void *) uc->uc_mcontext.gregs[REG_EIP];
277 strings = backtrace_symbols(trace, trace_size);
278 fprintf(stderr,
"%s %s [%s@%s:%d] Backtrace (size = %d) with %s\n",
279 pfx,ts,FFL,trace_size,
280 addr2linecmd ?
"addr2line-cmd" :
has_bfd ?
"BFD-method" :
"plain hex-dump");
281 if (strings && trace_size > 0) {
287 strcpy(addr2linecmd,TOSTR(ADDR2LINE));
288 strcat(addr2linecmd,
" -fs -e '");
289 strcat(addr2linecmd,a_out);
290 strcat(addr2linecmd,
"'");
291 for (i = 0; i < trace_size; i++) {
294 snprintf(s,
sizeof(s),
" %p",trace[i]);
297 strcat(addr2linecmd,s);
299 if (getenv(
"LD_PRELOAD")) {
300 static char ld_preload[] =
"LD_PRELOAD=";
303 fprintf(stderr,
"%s %s [%s@%s:%d] %s\n",
304 pfx,ts,FFL,addr2linecmd);
305 fp = popen(addr2linecmd,
"r");
309 for (i = 0; i < trace_size; i++) {
312 if (!feof(fp) && fgets(func, LINELEN, fp)) {
314 if (!feof(fp) && fgets(line, LINELEN, fp)) {
315 char *
nl = strchr(func,
'\n');
316 const char *last_slash = strrchr(strings[i],
'/');
317 if (last_slash) last_slash++;
else last_slash = strings[
i];
319 nl = strchr(line,
'\n');
321 fprintf(stderr,
"%s %s [%s@%s:%d] [%d]: %s : %s() at %s\n", pfx, ts, FFL,i, last_slash, func, line);
325 if (!ok) fprintf(stderr,
"%s %s [%s@%s:%d] [%d]: %s\n", pfx, ts, FFL,i, strings[i]);
333 for (i = 0 ; i < trace_size; ++
i) {
335 const char *last_slash = strrchr(strings[i],
'/');
336 if (last_slash) last_slash++;
else last_slash = strings[
i];
339 fprintf(stderr,
"%s %s [%s@%s:%d] [%d]: %s : %s() at %s:%u\n",pfx,ts,FFL,i,last_slash,b.func,b.file,b.lineno);
342 fprintf(stderr,
"%s %s [%s@%s:%d] [%d]: %s : %p\n",pfx,ts,FFL,i,last_slash,trace[i]);
349 backtrace_symbols_fd(trace, trace_size, fd);
351 if (strings) free(strings);
355 if (!sigcontextptr_given)
goto finish;
357 #if defined(PSTACKTRACE) 359 if (access(TOSTR(PSTACKTRACE),X_OK) == 0) {
360 char cmd[
sizeof(TOSTR(PSTACKTRACE)) + 20];
361 snprintf(cmd,
sizeof(cmd),
"%s %d", TOSTR(PSTACKTRACE),
pid);
372 fprintf(stderr,
"%s %s [%s@%s:%d] End of backtrace(s)\n",pfx,ts,FFL);
385 void LinuxTraceBack(
const char *prefix,
const char *timestr,
void *sigcontextptr) { }
398 #if !defined(GNUDEBUGGER) 399 #define GNUDEBUGGER /usr/bin/gdb 404 char *gdb = getenv(
"GNUDEBUGGER");
406 (access(TOSTR(GNUDEBUGGER),X_OK) == 0) &&
408 strequ(gdb,
"true") ||
409 strequ(gdb,
"TRUE"))) {
411 pid_t
pid = getpid();
414 "[gdb_trbk] : Invoking %s ...\n",
417 "set +e; /bin/echo '" 420 "set pagination off\n" 421 "set print elements 16\n" 422 "set print repeats 3\n" 423 "set print sevenbit-strings on\n" 425 "quit\n' > ./gdb_drhook.%d ; " 426 "%s -x ./gdb_drhook.%d -q -n -f -batch %s %d < /dev/null ; " 427 "/bin/rm -f ./gdb_drhook.%d" 429 , TOSTR(GNUDEBUGGER), pid, a_out, pid
444 #if !defined(DBXDEBUGGER) 445 #define DBXDEBUGGER /usr/bin/dbx 450 char *dbx = getenv(
"DBXDEBUGGER");
452 (access(TOSTR(DBXDEBUGGER),X_OK) == 0) &&
454 strequ(dbx,
"true") ||
455 strequ(dbx,
"TRUE"))) {
456 pid_t
pid = getpid();
460 const char *qopt =
" -q";
462 const char *qopt =
"";
465 "[dbx_trbk] : Invoking %s ...\n",
467 if (a_out && (access(a_out,X_OK|R_OK) == 0)) {
469 "set +e; /bin/echo 'where; quit; '" 471 TOSTR(DBXDEBUGGER), qopt, a_out, pid);
475 "set +e; /bin/echo 'where; quit; '" 477 TOSTR(DBXDEBUGGER), qopt, pid);
503 abfd = bfd_openr(a_out, 0);
505 perror(
"bfd_openr failed: ");
509 bfd_check_format(
abfd,bfd_object);
511 unsigned int storage_needed = bfd_get_symtab_upper_bound(
abfd);
512 syms = (asymbol **) malloc(storage_needed);
513 unsigned int cSymbols = bfd_canonicalize_symtab(
abfd,
syms);
515 text = bfd_get_section_by_name(
abfd,
".text");
526 long offset = (long)(address -
text->vma);
528 memset(b,0x0,
sizeof(*b));
529 if (bfd_find_nearest_line(
abfd,
text,
syms, offset, &b->file, &b->func, &b->lineno) && b->file && b->func) {
530 const char *last_slash = strrchr(b->file,
'/');
531 if (last_slash) b->file = last_slash + 1;
535 static const char qmarks[] =
"??";
537 static char *s = NULL;
541 loc_lbr = strchr(s,
'(');
543 char *loc_add = NULL;
545 loc_add = strchr(loc_lbr,
'+');
546 if (loc_add) *loc_add = 0;
553 if (!b->file) b->file = qmarks;
const char * ec_GetArgs(int argno)
void LinuxTraceBack(const char *prefix, const char *timestr, void *sigcontextptr)
static void SetMasterThreadsStackSizeBeforeMain()
static int ResolveViaBFD(void *address, BFD_t *b, const char *str)
int snprintf(char *str, size_t size, const char *format,...)
void __attribute__((constructor))
static char prealloc_addr2linecmd[len_addr2linecmd]