// Interpret pc/ln table, saving the subpiece for each func. static void splitpcln(void) { int32 line; uintptr pc; byte *p, *ep; Func *f, *ef; int32 *v; // TODO(rsc): Remove once TODO at top of file is done. if(goos != nil && strcmp((uint8*)goos, (uint8*)"nacl") == 0) return; if(goos != nil && strcmp((uint8*)goos, (uint8*)"pchw") == 0) return; // pc/ln table bounds #ifdef __MINGW__ v = get_symdat_addr(); p = (byte*)v+8; #else v = SYMCOUNTS; p = SYMDATA; #endif p += v[0]; ep = p+v[1]; f = func; ef = func + nfunc; pc = func[0].entry; // text base f->pcln.array = p; f->pc0 = pc - PcQuant; line = 0; for(; p < ep; p++) { if(f < ef && pc > (f+1)->entry) { f->pcln.len = p - f->pcln.array; f->pcln.cap = f->pcln.len; f++; f->pcln.array = p; f->pc0 = pc; f->ln0 = line; } if(*p == 0) { // 4 byte add to line line += (p[1]<<24) | (p[2]<<16) | (p[3]<<8) | p[4]; p += 4; } else if(*p <= 64) { line += *p; } else if(*p <= 128) { line -= *p - 64; } else { pc += PcQuant*(*p - 129); } pc += PcQuant; } if(f < ef) { f->pcln.len = p - f->pcln.array; f->pcln.cap = f->pcln.len; } }
// Walk over symtab, calling fn(&s) for each symbol. static void walksymtab(void (*fn)(Sym*)) { int32 *v; byte *p, *ep, *q; Sym s; // TODO(rsc): Remove once TODO at top of file is done. if(goos != nil && strcmp((uint8*)goos, (uint8*)"nacl") == 0) return; if(goos != nil && strcmp((uint8*)goos, (uint8*)"pchw") == 0) return; #ifdef __MINGW__ v = get_symdat_addr(); p = (byte*)v+8; #else v = SYMCOUNTS; p = SYMDATA; #endif ep = p + v[0]; while(p < ep) { if(p + 7 > ep) break; s.value = ((uint32)p[0]<<24) | ((uint32)p[1]<<16) | ((uint32)p[2]<<8) | ((uint32)p[3]); if(!(p[4]&0x80)) break; s.symtype = p[4] & ~0x80; p += 5; s.name = p; if(s.symtype == 'z' || s.symtype == 'Z') { // path reference string - skip first byte, // then 2-byte pairs ending at two zeros. q = p+1; for(;;) { if(q+2 > ep) return; if(q[0] == '\0' && q[1] == '\0') break; q += 2; } p = q+2; } else { q = mchr(p, '\0', ep); if(q == nil) break; p = q+1; } p += 4; // go type fn(&s); } }
// Walk over symtab, calling fn(&s) for each symbol. static void walksymtab(void (*fn)(Sym*)) { int32 *v; byte *p, *ep, *q; Sym s; if(symdat == nil) return; #ifdef __WINDOWS__ v = get_symdat_addr(); p = (byte*)v+8; #else v = symdat; p = (byte*)(symdat+2); #endif ep = p + v[0]; while(p < ep) { if(p + 7 > ep) break; s.value = ((uint32)p[0]<<24) | ((uint32)p[1]<<16) | ((uint32)p[2]<<8) | ((uint32)p[3]); if(!(p[4]&0x80)) break; s.symtype = p[4] & ~0x80; p += 5; s.name = p; if(s.symtype == 'z' || s.symtype == 'Z') { // path reference string - skip first byte, // then 2-byte pairs ending at two zeros. q = p+1; for(;;) { if(q+2 > ep) return; if(q[0] == '\0' && q[1] == '\0') break; q += 2; } p = q+2; }else{ q = mchr(p, '\0', ep); if(q == nil) break; p = q+1; } p += 4; // go type fn(&s); } }
// Interpret pc/ln table, saving the subpiece for each func. static void splitpcln(void) { int32 line; uintptr pc; byte *p, *ep; Func *f, *ef; int32 *v; int32 pcquant; switch(thechar) { case '5': pcquant = 4; break; default: // 6, 8 pcquant = 1; break; } if(symdat == nil) return; // pc/ln table bounds #ifdef __WINDOWS__ v = get_symdat_addr(); p = (byte*)v+8; #else v = symdat; p = (byte*)(symdat+2); #endif p += v[0]; ep = p+v[1]; f = func; ef = func + nfunc; pc = func[0].entry; // text base f->pcln.array = p; f->pc0 = pc - pcquant; line = 0; for(; p < ep; p++) { if(f < ef && pc > (f+1)->entry) { f->pcln.len = p - f->pcln.array; f->pcln.cap = f->pcln.len; f++; f->pcln.array = p; f->pc0 = pc; f->ln0 = line; } if(*p == 0) { // 4 byte add to line line += (p[1]<<24) | (p[2]<<16) | (p[3]<<8) | p[4]; p += 4; } else if(*p <= 64) { line += *p; } else if(*p <= 128) { line -= *p - 64; } else { pc += pcquant*(*p - 129); } pc += pcquant; } if(f < ef) { f->pcln.len = p - f->pcln.array; f->pcln.cap = f->pcln.len; } }