void get_coordinate(unsigned long addr, const char *exec, char **func, char **coord) { char cmd[BUFSIZ]; char line[BUFSIZ]; FILE *pp; int len; *func = NULL; *coord = NULL; if (i_have_addr2line) { snprintf(cmd, sizeof(cmd), "%s %#lx -f -e %s", prog_path, addr, exec); pp = popen(cmd, "r"); if (pp != NULL) { while (fgets(line, sizeof(line), pp)) { line[strlen(line) - 1] = '\0'; if ((strstr(line, "addr2line") != NULL) || (strstr(line, "??") != NULL)) { pclose(pp); goto dontknow; } if (strstr(line, ":") != NULL) { get_coord_line(line, coord); } else { get_func_line(line, func); } } pclose(pp); return; } else { goto dontknow; } } else { dontknow: *func = malloc(DEFAULT_LEN); if (*func != NULL) { strcpy(*func, "??"); } else { fprintf(stderr, "malloc() failed. %d %s\n", errno, strerror(errno)); exit(1); } *coord = malloc(DEFAULT_LEN); if (*coord != NULL) { strcpy(*coord, "??:0"); } else { fprintf(stderr, "malloc() failed. %d %s\n", errno, strerror(errno)); exit(1); } return; } }
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg) { long s1, s2, e1, e2, lctx; xdchange_t *xch, *xche; long funclineprev = -1; struct func_line func_line = { 0 }; if (xecfg->flags & XDL_EMIT_COMMON) return xdl_emit_common(xe, xscr, ecb, xecfg); for (xch = xscr; xch; xch = xche->next) { xche = xdl_get_hunk(xch, xecfg); s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0); s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0); if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) { long fs1 = get_func_line(xe, xecfg, NULL, xch->i1, -1); if (fs1 < 0) fs1 = 0; if (fs1 < s1) { s2 -= s1 - fs1; s1 = fs1; } } again: lctx = xecfg->ctxlen; lctx = XDL_MIN(lctx, xe->xdf1.nrec - (xche->i1 + xche->chg1)); lctx = XDL_MIN(lctx, xe->xdf2.nrec - (xche->i2 + xche->chg2)); e1 = xche->i1 + xche->chg1 + lctx; e2 = xche->i2 + xche->chg2 + lctx; if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) { long fe1 = get_func_line(xe, xecfg, NULL, xche->i1 + xche->chg1, xe->xdf1.nrec); if (fe1 < 0) fe1 = xe->xdf1.nrec; if (fe1 > e1) { e2 += fe1 - e1; e1 = fe1; } /* * Overlap with next change? Then include it * in the current hunk and start over to find * its new end. */ if (xche->next) { long l = xche->next->i1; if (l <= e1 || get_func_line(xe, xecfg, NULL, l, e1) < 0) { xche = xche->next; goto again; } } } /* * Emit current hunk header. */ if (xecfg->flags & XDL_EMIT_FUNCNAMES) { get_func_line(xe, xecfg, &func_line, s1 - 1, funclineprev); funclineprev = s1 - 1; } if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, func_line.buf, func_line.len, ecb) < 0) return -1; /* * Emit pre-context. */ for (; s2 < xch->i2; s2++) if (xdl_emit_record(&xe->xdf2, s2, " ", ecb) < 0) return -1; for (s1 = xch->i1, s2 = xch->i2;; xch = xch->next) { /* * Merge previous with current change atom. */ for (; s1 < xch->i1 && s2 < xch->i2; s1++, s2++) if (xdl_emit_record(&xe->xdf2, s2, " ", ecb) < 0) return -1; /* * Removes lines from the first file. */ for (s1 = xch->i1; s1 < xch->i1 + xch->chg1; s1++) if (xdl_emit_record(&xe->xdf1, s1, "-", ecb) < 0) return -1; /* * Adds lines from the second file. */ for (s2 = xch->i2; s2 < xch->i2 + xch->chg2; s2++) if (xdl_emit_record(&xe->xdf2, s2, "+", ecb) < 0) return -1; if (xch == xche) break; s1 = xch->i1 + xch->chg1; s2 = xch->i2 + xch->chg2; } /* * Emit post-context. */ for (s2 = xche->i2 + xche->chg2; s2 < e2; s2++) if (xdl_emit_record(&xe->xdf2, s2, " ", ecb) < 0) return -1; } return 0; }