github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/liblink/obj.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include <u.h> 6 #include <libc.h> 7 #include <bio.h> 8 #include <link.h> 9 10 enum 11 { 12 HISTSZ = 10, 13 NSYM = 50, 14 }; 15 16 int 17 linklinefmt(Link *ctxt, Fmt *fp) 18 { 19 struct 20 { 21 Hist* incl; /* start of this include file */ 22 int32 idel; /* delta line number to apply to include */ 23 Hist* line; /* start of this #line directive */ 24 int32 ldel; /* delta line number to apply to #line */ 25 } a[HISTSZ]; 26 int32 lno, d; 27 int i, n; 28 Hist *h; 29 30 lno = va_arg(fp->args, int32); 31 32 n = 0; 33 for(h=ctxt->hist; h!=nil; h=h->link) { 34 if(h->offset < 0) 35 continue; 36 if(lno < h->line) 37 break; 38 if(h->name) { 39 if(h->offset > 0) { 40 // #line directive 41 if(n > 0 && n < HISTSZ) { 42 a[n-1].line = h; 43 a[n-1].ldel = h->line - h->offset + 1; 44 } 45 } else { 46 // beginning of file 47 if(n < HISTSZ) { 48 a[n].incl = h; 49 a[n].idel = h->line; 50 a[n].line = 0; 51 } 52 n++; 53 } 54 continue; 55 } 56 n--; 57 if(n > 0 && n < HISTSZ) { 58 d = h->line - a[n].incl->line; 59 a[n-1].ldel += d; 60 a[n-1].idel += d; 61 } 62 } 63 64 if(n > HISTSZ) 65 n = HISTSZ; 66 67 for(i=n-1; i>=0; i--) { 68 if(i != n-1) { 69 if(fp->flags & ~(FmtWidth|FmtPrec)) 70 break; 71 fmtprint(fp, " "); 72 } 73 if(ctxt->debugline || (fp->flags&FmtLong)) 74 fmtprint(fp, "%s/", ctxt->pathname); 75 if(a[i].line) 76 fmtprint(fp, "%s:%d[%s:%d]", 77 a[i].line->name, lno-a[i].ldel+1, 78 a[i].incl->name, lno-a[i].idel+1); 79 else 80 fmtprint(fp, "%s:%d", 81 a[i].incl->name, lno-a[i].idel+1); 82 lno = a[i].incl->line - 1; // now print out start of this file 83 } 84 if(n == 0) 85 fmtprint(fp, "<unknown line number>"); 86 87 return 0; 88 } 89 90 // Does s have t as a path prefix? 91 // That is, does s == t or does s begin with t followed by a slash? 92 // For portability, we allow ASCII case folding, so that haspathprefix("a/b/c", "A/B") is true. 93 // Similarly, we allow slash folding, so that haspathprefix("a/b/c", "a\\b") is true. 94 static int 95 haspathprefix(char *s, char *t) 96 { 97 int i, cs, ct; 98 99 if(t == nil) 100 return 0; 101 for(i=0; t[i]; i++) { 102 cs = s[i]; 103 ct = t[i]; 104 if('A' <= cs && cs <= 'Z') 105 cs += 'a' - 'A'; 106 if('A' <= ct && ct <= 'Z') 107 ct += 'a' - 'A'; 108 if(cs == '\\') 109 cs = '/'; 110 if(ct == '\\') 111 ct = '/'; 112 if(cs != ct) 113 return 0; 114 } 115 return s[i] == '\0' || s[i] == '/' || s[i] == '\\'; 116 } 117 118 // This is a simplified copy of linklinefmt above. 119 // It doesn't allow printing the full stack, and it returns the file name and line number separately. 120 // TODO: Unify with linklinefmt somehow. 121 void 122 linkgetline(Link *ctxt, int32 line, LSym **f, int32 *l) 123 { 124 struct 125 { 126 Hist* incl; /* start of this include file */ 127 int32 idel; /* delta line number to apply to include */ 128 Hist* line; /* start of this #line directive */ 129 int32 ldel; /* delta line number to apply to #line */ 130 } a[HISTSZ]; 131 int32 lno, d, dlno; 132 int n; 133 Hist *h; 134 char buf[1024], buf1[1024], *file; 135 136 lno = line; 137 n = 0; 138 for(h=ctxt->hist; h!=nil; h=h->link) { 139 if(h->offset < 0) 140 continue; 141 if(lno < h->line) 142 break; 143 if(h->name) { 144 if(h->offset > 0) { 145 // #line directive 146 if(n > 0 && n < HISTSZ) { 147 a[n-1].line = h; 148 a[n-1].ldel = h->line - h->offset + 1; 149 } 150 } else { 151 // beginning of file 152 if(n < HISTSZ) { 153 a[n].incl = h; 154 a[n].idel = h->line; 155 a[n].line = 0; 156 } 157 n++; 158 } 159 continue; 160 } 161 n--; 162 if(n > 0 && n < HISTSZ) { 163 d = h->line - a[n].incl->line; 164 a[n-1].ldel += d; 165 a[n-1].idel += d; 166 } 167 } 168 169 if(n > HISTSZ) 170 n = HISTSZ; 171 172 if(n <= 0) { 173 *f = linklookup(ctxt, "??", HistVersion); 174 *l = 0; 175 return; 176 } 177 178 n--; 179 if(a[n].line) { 180 file = a[n].line->name; 181 dlno = a[n].ldel-1; 182 } else { 183 file = a[n].incl->name; 184 dlno = a[n].idel-1; 185 } 186 if((!ctxt->windows && file[0] == '/') || (ctxt->windows && file[1] == ':') || file[0] == '<') 187 snprint(buf, sizeof buf, "%s", file); 188 else 189 snprint(buf, sizeof buf, "%s/%s", ctxt->pathname, file); 190 191 // Remove leading ctxt->trimpath, or else rewrite $GOROOT to $GOROOT_FINAL. 192 if(haspathprefix(buf, ctxt->trimpath)) { 193 if(strlen(buf) == strlen(ctxt->trimpath)) 194 strcpy(buf, "??"); 195 else { 196 snprint(buf1, sizeof buf1, "%s", buf+strlen(ctxt->trimpath)+1); 197 if(buf1[0] == '\0') 198 strcpy(buf1, "??"); 199 strcpy(buf, buf1); 200 } 201 } else if(ctxt->goroot_final != nil && haspathprefix(buf, ctxt->goroot)) { 202 snprint(buf1, sizeof buf1, "%s%s", ctxt->goroot_final, buf+strlen(ctxt->goroot)); 203 strcpy(buf, buf1); 204 } 205 206 lno -= dlno; 207 *f = linklookup(ctxt, buf, HistVersion); 208 *l = lno; 209 } 210 211 void 212 linklinehist(Link *ctxt, int lineno, char *f, int offset) 213 { 214 Hist *h; 215 216 if(0) // debug['f'] 217 if(f) { 218 if(offset) 219 print("%4d: %s (#line %d)\n", lineno, f, offset); 220 else 221 print("%4d: %s\n", lineno, f); 222 } else 223 print("%4d: <pop>\n", lineno); 224 225 h = malloc(sizeof(Hist)); 226 memset(h, 0, sizeof *h); 227 h->name = f; 228 h->line = lineno; 229 h->offset = offset; 230 h->link = nil; 231 if(ctxt->ehist == nil) { 232 ctxt->hist = h; 233 ctxt->ehist = h; 234 return; 235 } 236 ctxt->ehist->link = h; 237 ctxt->ehist = h; 238 } 239 240 void 241 linkprfile(Link *ctxt, int32 l) 242 { 243 int i, n; 244 Hist a[HISTSZ], *h; 245 int32 d; 246 247 n = 0; 248 for(h = ctxt->hist; h != nil; h = h->link) { 249 if(l < h->line) 250 break; 251 if(h->name) { 252 if(h->offset == 0) { 253 if(n >= 0 && n < HISTSZ) 254 a[n] = *h; 255 n++; 256 continue; 257 } 258 if(n > 0 && n < HISTSZ) 259 if(a[n-1].offset == 0) { 260 a[n] = *h; 261 n++; 262 } else 263 a[n-1] = *h; 264 continue; 265 } 266 n--; 267 if(n >= 0 && n < HISTSZ) { 268 d = h->line - a[n].line; 269 for(i=0; i<n; i++) 270 a[i].line += d; 271 } 272 } 273 if(n > HISTSZ) 274 n = HISTSZ; 275 for(i=0; i<n; i++) 276 print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1)); 277 } 278 279 /* 280 * start a new Prog list. 281 */ 282 Plist* 283 linknewplist(Link *ctxt) 284 { 285 Plist *pl; 286 287 pl = malloc(sizeof(*pl)); 288 memset(pl, 0, sizeof *pl); 289 if(ctxt->plist == nil) 290 ctxt->plist = pl; 291 else 292 ctxt->plast->link = pl; 293 ctxt->plast = pl; 294 295 return pl; 296 }