13e12c5d1SDavid du Colombier /* 2bd389b36SDavid du Colombier * kobj.c - identify and parse a sparc object file 33e12c5d1SDavid du Colombier */ 43e12c5d1SDavid du Colombier #include <u.h> 53e12c5d1SDavid du Colombier #include <libc.h> 63e12c5d1SDavid du Colombier #include <bio.h> 73e12c5d1SDavid du Colombier #include "kc/k.out.h" 83e12c5d1SDavid du Colombier #include "obj.h" 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier typedef struct Addr Addr; 113e12c5d1SDavid du Colombier struct Addr 123e12c5d1SDavid du Colombier { 133e12c5d1SDavid du Colombier char type; 143e12c5d1SDavid du Colombier char sym; 153e12c5d1SDavid du Colombier char name; 163e12c5d1SDavid du Colombier }; 17bd389b36SDavid du Colombier static Addr addr(Biobuf*); 183e12c5d1SDavid du Colombier static char type2char(int); 19bd389b36SDavid du Colombier static void skip(Biobuf*, int); 203e12c5d1SDavid du Colombier 213e12c5d1SDavid du Colombier 223e12c5d1SDavid du Colombier int 233e12c5d1SDavid du Colombier _isk(char *s) 243e12c5d1SDavid du Colombier { 253e12c5d1SDavid du Colombier return s[0] == ANAME /* ANAME */ 263e12c5d1SDavid du Colombier && s[1] == D_FILE /* type */ 273e12c5d1SDavid du Colombier && s[2] == 1 /* sym */ 283e12c5d1SDavid du Colombier && s[3] == '<'; /* name of file */ 293e12c5d1SDavid du Colombier } 303e12c5d1SDavid du Colombier 313e12c5d1SDavid du Colombier 32bd389b36SDavid du Colombier int 33bd389b36SDavid du Colombier _readk(Biobuf *bp, Prog *p) 343e12c5d1SDavid du Colombier { 35219b2ee8SDavid du Colombier int as, n; 363e12c5d1SDavid du Colombier Addr a; 373e12c5d1SDavid du Colombier 38bd389b36SDavid du Colombier as = Bgetc(bp); /* as */ 393e12c5d1SDavid du Colombier if(as < 0) 403e12c5d1SDavid du Colombier return 0; 413e12c5d1SDavid du Colombier p->kind = aNone; 42*061a3f44SDavid du Colombier if(as == ANAME || as == ASIGNAME){ 43*061a3f44SDavid du Colombier if(as == ASIGNAME) 44*061a3f44SDavid du Colombier skip(bp, 4); /* signature */ 453e12c5d1SDavid du Colombier p->kind = aName; 46bd389b36SDavid du Colombier p->type = type2char(Bgetc(bp)); /* type */ 47bd389b36SDavid du Colombier p->sym = Bgetc(bp); /* sym */ 48219b2ee8SDavid du Colombier n = 0; 49219b2ee8SDavid du Colombier for(;;) { 50219b2ee8SDavid du Colombier as = Bgetc(bp); 51219b2ee8SDavid du Colombier if(as < 0) 52219b2ee8SDavid du Colombier return 0; 53219b2ee8SDavid du Colombier n++; 54219b2ee8SDavid du Colombier if(as == 0) 55219b2ee8SDavid du Colombier break; 563e12c5d1SDavid du Colombier } 57219b2ee8SDavid du Colombier p->id = malloc(n); 58219b2ee8SDavid du Colombier if(p->id == 0) 59219b2ee8SDavid du Colombier return 0; 60219b2ee8SDavid du Colombier Bseek(bp, -n, 1); 61219b2ee8SDavid du Colombier if(Bread(bp, p->id, n) != n) 62219b2ee8SDavid du Colombier return 0; 63bd389b36SDavid du Colombier return 1; 643e12c5d1SDavid du Colombier } 653e12c5d1SDavid du Colombier if(as == ATEXT) 663e12c5d1SDavid du Colombier p->kind = aText; 673e12c5d1SDavid du Colombier else if(as == AGLOBL) 683e12c5d1SDavid du Colombier p->kind = aData; 69bd389b36SDavid du Colombier skip(bp, 5); /* reg (1 byte); lineno (4 bytes) */ 70bd389b36SDavid du Colombier a = addr(bp); 71bd389b36SDavid du Colombier addr(bp); 72bd389b36SDavid du Colombier if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN) 733e12c5d1SDavid du Colombier p->kind = aNone; 743e12c5d1SDavid du Colombier p->sym = a.sym; 75bd389b36SDavid du Colombier return 1; 763e12c5d1SDavid du Colombier } 773e12c5d1SDavid du Colombier 783e12c5d1SDavid du Colombier static Addr 79bd389b36SDavid du Colombier addr(Biobuf *bp) 803e12c5d1SDavid du Colombier { 813e12c5d1SDavid du Colombier Addr a; 82bd389b36SDavid du Colombier long off; 833e12c5d1SDavid du Colombier 84bd389b36SDavid du Colombier a.type = Bgetc(bp); /* a.type */ 85bd389b36SDavid du Colombier skip(bp, 1); /* reg */ 86bd389b36SDavid du Colombier a.sym = Bgetc(bp); /* sym index */ 87bd389b36SDavid du Colombier a.name = Bgetc(bp); /* sym type */ 883e12c5d1SDavid du Colombier switch(a.type) { 893e12c5d1SDavid du Colombier default: 903e12c5d1SDavid du Colombier case D_NONE: case D_REG: case D_FREG: case D_CREG: case D_PREG: 913e12c5d1SDavid du Colombier break; 923e12c5d1SDavid du Colombier case D_BRANCH: 933e12c5d1SDavid du Colombier case D_OREG: 943e12c5d1SDavid du Colombier case D_ASI: 953e12c5d1SDavid du Colombier case D_CONST: 96bd389b36SDavid du Colombier off = Bgetc(bp); 97bd389b36SDavid du Colombier off |= Bgetc(bp) << 8; 98bd389b36SDavid du Colombier off |= Bgetc(bp) << 16; 99bd389b36SDavid du Colombier off |= Bgetc(bp) << 24; 100bd389b36SDavid du Colombier if(off < 0) 101bd389b36SDavid du Colombier off = -off; 102bd389b36SDavid du Colombier if(a.sym!=0 && (a.name==D_PARAM || a.name==D_AUTO)) 103bd389b36SDavid du Colombier _offset(a.sym, off); 1043e12c5d1SDavid du Colombier break; 1053e12c5d1SDavid du Colombier case D_SCONST: 106bd389b36SDavid du Colombier skip(bp, NSNAME); 1073e12c5d1SDavid du Colombier break; 1083e12c5d1SDavid du Colombier case D_FCONST: 109bd389b36SDavid du Colombier skip(bp, 8); 1103e12c5d1SDavid du Colombier break; 1113e12c5d1SDavid du Colombier } 1123e12c5d1SDavid du Colombier return a; 1133e12c5d1SDavid du Colombier } 1143e12c5d1SDavid du Colombier 1153e12c5d1SDavid du Colombier 1163e12c5d1SDavid du Colombier static char 1173e12c5d1SDavid du Colombier type2char(int t) 1183e12c5d1SDavid du Colombier { 1193e12c5d1SDavid du Colombier switch(t){ 1203e12c5d1SDavid du Colombier case D_EXTERN: return 'U'; 1213e12c5d1SDavid du Colombier case D_STATIC: return 'b'; 1223e12c5d1SDavid du Colombier case D_AUTO: return 'a'; 1233e12c5d1SDavid du Colombier case D_PARAM: return 'p'; 1243e12c5d1SDavid du Colombier default: return UNKNOWN; 1253e12c5d1SDavid du Colombier } 1263e12c5d1SDavid du Colombier } 127bd389b36SDavid du Colombier 128bd389b36SDavid du Colombier static void 129bd389b36SDavid du Colombier skip(Biobuf *bp, int n) 130bd389b36SDavid du Colombier { 131bd389b36SDavid du Colombier while (n-- > 0) 132bd389b36SDavid du Colombier Bgetc(bp); 133bd389b36SDavid du Colombier } 134