diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-05-03 21:00:17 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-05-03 21:00:17 +0200 |
commit | 14b69dcde0dfbb72df721424571d07cdf3dcbf05 (patch) | |
tree | 26fac46e8a0b6462d7e9e5f388468bee09eb3ce6 /sys/src/libmach/7obj.c | |
parent | 9920ecc04b87cab3968f7f0c286b264bd31e132f (diff) |
libmach: initial arm64 support
Diffstat (limited to 'sys/src/libmach/7obj.c')
-rw-r--r-- | sys/src/libmach/7obj.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/sys/src/libmach/7obj.c b/sys/src/libmach/7obj.c new file mode 100644 index 000000000..47b219a86 --- /dev/null +++ b/sys/src/libmach/7obj.c @@ -0,0 +1,150 @@ +/* + * 7obj.c - identify and parse an arm64 object file + */ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include "7c/7.out.h" +#include "obj.h" + +typedef struct Addr Addr; +struct Addr +{ + char type; + char sym; + char name; +}; +static Addr addr(Biobuf*); +static char type2char(int); +static void skip(Biobuf*, int); + +int +_is7(char *s) +{ + return s[0] == (ANAME&0xff) /* aslo = ANAME */ + && s[1] == ((ANAME>>8)&0xff) + && s[2] == D_FILE /* type */ + && s[3] == 1 /* sym */ + && s[4] == '<'; /* name of file */ +} + +int +_read7(Biobuf *bp, Prog *p) +{ + int as, n; + Addr a; + + as = (uchar)Bgetc(bp); /* as */ + as |= (uchar)Bgetc(bp)<<8; + if(as <= AXXX || as >= ALAST) + return 0; + p->kind = aNone; + p->sig = 0; + if(as == ANAME || as == ASIGNAME){ + if(as == ASIGNAME){ + Bread(bp, &p->sig, 4); + p->sig = leswal(p->sig); + } + p->kind = aName; + p->type = type2char(Bgetc(bp)); /* type */ + p->sym = Bgetc(bp); /* sym */ + n = 0; + for(;;) { + as = Bgetc(bp); + if(as < 0) + return 0; + n++; + if(as == 0) + break; + } + p->id = malloc(n); + if(p->id == 0) + return 0; + Bseek(bp, -n, 1); + if(Bread(bp, p->id, n) != n) + return 0; + return 1; + } + if(as == ATEXT) + p->kind = aText; + else if(as == AGLOBL) + p->kind = aData; + skip(bp, 5); /* reg(1) lineno(4) */ + a = addr(bp); + addr(bp); + if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN) + p->kind = aNone; + p->sym = a.sym; + return 1; +} + +static Addr +addr(Biobuf *bp) +{ + Addr a; + long off; + + a.type = Bgetc(bp); /* a.type */ + skip(bp,1); /* reg */ + a.sym = Bgetc(bp); /* sym index */ + a.name = Bgetc(bp); /* sym type */ + switch(a.type){ + default: + case D_NONE: + case D_REG: + case D_SP: + case D_FREG: + case D_VREG: + case D_COND: + break; + + case D_OREG: + case D_XPRE: + case D_XPOST: + case D_CONST: + case D_BRANCH: + case D_SHIFT: + case D_EXTREG: + case D_ROFF: + case D_SPR: + off = Bgetc(bp); + off |= Bgetc(bp) << 8; + off |= Bgetc(bp) << 16; + off |= Bgetc(bp) << 24; + if(off < 0) + off = -off; + if(a.sym && (a.name==D_PARAM || a.name==D_AUTO)) + _offset(a.sym, off); + break; + case D_DCONST: + skip(bp, 8); + break; + case D_SCONST: + skip(bp, NSNAME); + break; + case D_FCONST: + skip(bp, 8); + break; + } + return a; +} + +static char +type2char(int t) +{ + switch(t){ + case D_EXTERN: return 'U'; + case D_STATIC: return 'b'; + case D_AUTO: return 'a'; + case D_PARAM: return 'p'; + default: return UNKNOWN; + } +} + +static void +skip(Biobuf *bp, int n) +{ + while (n-- > 0) + Bgetc(bp); +} |