as: Align symbol and section with mach.h - scc - simple c99 compiler
 (HTM) git clone git://git.simple-cc.org/scc
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 7b484ddf2a8546ce55949d81cb177bbef416dcff
 (DIR) parent 70b4d78d91cd330d951b919534c0da553489be55
 (HTM) Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
       Date:   Sun, 11 Feb 2024 16:19:30 +0100
       
       as: Align symbol and section with mach.h
       
       As uses types very similar to the types used
       in mach.h and if we want to use libmach in
       as then we have to align these structures
       to avoid the collition between them.
       
       Diffstat:
         M include/scc/scc/mach.h              |      11 +++++++++++
         M src/cmd/as/as.h                     |      47 ++++++++++++++++---------------
         M src/cmd/as/binfmt.c                 |      24 +++++++++++++++++-------
         M src/cmd/as/ins.c                    |       2 +-
         M src/cmd/as/symbol.c                 |     154 +++++++++++++++++++++----------
         M src/libmach/libmach.h               |       1 -
       
       6 files changed, 160 insertions(+), 79 deletions(-)
       ---
 (DIR) diff --git a/include/scc/scc/mach.h b/include/scc/scc/mach.h
       @@ -60,12 +60,21 @@ struct section {
                char *name;
                unsigned long long base;
                unsigned long long size;
       +        unsigned long long curpc;
       +        unsigned long long pc;
       +
                unsigned flags;
                int index;
                int align;
       +        int fill;
                char type;
        };
        
       +/**
       + * @stype: Used internally by libmach
       + * @dtype: Coff debug type
       + * @flags: Used only by the assembler
       + */
        struct symbol {
                char *name;
                unsigned long long size;
       @@ -74,6 +83,8 @@ struct symbol {
                int section;
                char type;
                int stype;
       +        int dtype;
       +        unsigned flags;
        };
        
        extern int archive(FILE *fp);
 (DIR) diff --git a/src/cmd/as/as.h b/src/cmd/as/as.h
       @@ -108,29 +108,31 @@ struct op {
        };
        
        struct section {
       -        Symbol *sym;
       +        char *name;
       +        unsigned long long base;
       +        unsigned long long size;
       +        unsigned long long curpc;
       +        unsigned long long  pc;
       +
       +        unsigned flags;
       +        int index;
       +        int align;
       +        int fill;
       +        char type;
       +
                char *mem;
       -        unsigned char flags;
       -        unsigned char fill;
       -        unsigned char aligment;
       -        unsigned id;
       -        TUINT base;
       -        TUINT max;
       -        TUINT curpc;
       -        TUINT pc;
       -        struct section *next;
        };
        
        struct symbol {
                char *name;
       -        char *type;
       -        unsigned char flags;
       -        unsigned char pass;
       -        TUINT value;
       -        TUINT size;
       -        Section *section;
       -        struct symbol *next;
       -        struct symbol *hash;
       +        unsigned long long size;
       +        unsigned long long value;
       +        int index;
       +        int section;
       +        char type;
       +        int stype;
       +        int dtype;
       +        unsigned flags;
        };
        
        struct node {
       @@ -146,7 +148,6 @@ union yylval {
                Symbol *sym;
        };
        
       -
        /* symbol.c */
        extern void cleansecs(void);
        extern void isecs(void);
       @@ -156,8 +157,8 @@ extern Symbol *tmpsym(TUINT);
        extern void killtmp(void);
        extern int toobig(Node *, int);
        extern void dumpstab(char *);
       -
       -/* main.c */
       +extern Section *secindex(int);
       +int forallsecs(int (*)(Section *, void *), void *);
        extern Symbol *lookup(char *);
        extern Symbol *deflabel(char *);
        
       @@ -200,13 +201,13 @@ extern void writeout(char *);
         */
        extern unsigned long M, S, K;
        extern short hashmap[];
       -extern Section *cursec, *seclist;
       +extern Section *cursec;
        extern Ins instab[];
        extern Op optab[];
        extern int pass;
        extern TUINT maxaddr;
        extern int endian;
       -extern Symbol *linesym, *symlist;
       +extern Symbol *linesym;
        extern char *infile, *outfile;
        extern int endpass;
        extern int yytoken;
 (DIR) diff --git a/src/cmd/as/binfmt.c b/src/cmd/as/binfmt.c
       @@ -7,23 +7,33 @@
        
        #include "as.h"
        
       +static int
       +dumpsec(Section *sec, void *arg)
       +{
       +        FILE *fp = arg;
       +
       +        if (!sec->mem)
       +                return 0;
       +
       +        fwrite(sec->mem, sec->size, 1, fp);
       +        return 0;
       +}
       +
        void
        writeout(char *fname)
        {
       -        Section *sp;
                FILE *fp;
        
                if ((fp = fopen(fname, "wb")) == NULL)
                        goto error;
        
       -        for (sp = seclist; sp; sp = sp->next) {
       -                if (!sp->mem)
       -                        continue;
       -                fwrite(sp->mem, sp->max - sp->base, 1, fp);
       -        }
       +        forallsecs(dumpsec, fp);
       +        fflush(fp);
        
       -        if (fclose(fp))
       +        if (ferror(fp))
                        goto error;
       +
       +        fclose(fp);
                outfile = NULL;
        
                return;
 (DIR) diff --git a/src/cmd/as/ins.c b/src/cmd/as/ins.c
       @@ -149,7 +149,7 @@ symexp(int which, Op *op, Node **args)
                        sym->size = exp->value;
                        break;
                case TYPE:
       -                sym->type = xstrdup(exp->name);
       +                sym->dtype = exp->value;
                        break;
                }
        }
 (DIR) diff --git a/src/cmd/as/symbol.c b/src/cmd/as/symbol.c
       @@ -11,19 +11,33 @@
        #define HASHSIZ 64
        #define NALLOC  10
        
       -Section *cursec, *seclist;
       +struct lsymbol {
       +        Symbol sym;
       +        struct lsymbol *next;
       +        struct lsymbol *hash;
       +};
       +
       +struct lsection {
       +        Section s;
       +        struct lsection *next;
       +};
       +
       +Section *cursec;
        Section *sabs, *sbss, *sdata, *stext;
       -Symbol *linesym, *symlist;
       +Symbol *linesym;
        int pass;
        
       -static Symbol *hashtbl[HASHSIZ], *symlast, *cursym;
       +static struct lsection *seclist;
       +static struct lsymbol *hashtbl[HASHSIZ], *symlast, *symlist;
       +
       +static Symbol *cursym;
        static Alloc *tmpalloc;
        
        #ifndef NDEBUG
        void
        dumpstab(char *msg)
        {
       -        Symbol **bp, *sym;
       +        struct lsymbol **bp, *lp;
        
                fprintf(stderr, "%s\n", msg);
                for (bp = hashtbl; bp < &hashtbl[HASHSIZ]; ++bp) {
       @@ -31,9 +45,11 @@ dumpstab(char *msg)
                                continue;
        
                        fprintf(stderr, "[%d]", (int) (bp - hashtbl));
       -                for (sym = *bp; sym; sym = sym->hash) {
       +                for (lp = *bp; lp; lp = lp->hash) {
                                fprintf(stderr, " -> %s:%0X:%0X",
       -                               sym->name, sym->flags, sym->value);
       +                               lp->sym.name,
       +                               lp->sym.flags,
       +                               lp->sym.value);
                        }
                        putc('\n', stderr);
                }
       @@ -44,10 +60,10 @@ Symbol *
        lookup(char *name)
        {
                unsigned h;
       -        Symbol *sym, **list;
       +        Symbol *sym;
                int r, c, symtype;
       -        char *t;
       -        char buf[INTIDENTSIZ+1];
       +        struct lsymbol *lp, **list;
       +        char *t, buf[INTIDENTSIZ+1];
        
                if (*name == '.' && cursym) {
                        if (!cursym)
       @@ -63,26 +79,30 @@ lookup(char *name)
        
                c = toupper(*name);
                list = &hashtbl[h];
       -        for (sym = *list; sym; sym = sym->hash) {
       -                t = sym->name;
       +        for (lp = *list; lp; lp = lp->hash) {
       +                sym = &lp->sym;
       +                t = lp->sym.name;
                        if (c == toupper(*t) && !casecmp(t, name))
                                return sym;
                }
        
       -        sym = xmalloc(sizeof(*sym));
       -        sym->name = xstrdup(name);
       -        sym->flags = 0;
       -        sym->size = sym->value = 0;
       -        sym->section = cursec;
       -        sym->hash = *list;
       -        sym->next = NULL;
       +        lp = xmalloc(sizeof(*lp));
       +        lp->next = NULL;
       +        lp->hash = *list;
       +        *list = lp;
        
       -        *list = sym;
                if (symlast)
       -                symlast->next = sym;
       -        symlast = sym;
       +                symlast->next = lp;
       +        symlast = lp;
       +
                if (!symlist)
       -                symlist = sym;
       +                symlist = lp;
       +
       +        sym = &lp->sym;
       +        sym->name = xstrdup(name);
       +        sym->flags = 0;
       +        sym->size = sym->value = 0;
       +        sym->section = cursec ? cursec->index : -1;
        
                return sym;
        }
       @@ -119,7 +139,7 @@ deflabel(char *name)
                if (cursec->flags & SABS)
                        sym->flags |= FABS;
                sym->value = cursec->curpc;
       -        sym->section = cursec;
       +        sym->section = cursec->index;
        
                if (!local)
                        cursym = sym;
       @@ -152,21 +172,23 @@ toobig(Node *np, int type)
        }
        
        static void
       -incpc(int siz)
       +incpc(int nbytes)
        {
       +        unsigned long long siz;
                TUINT pc, curpc;
        
                pc = cursec->pc;
                curpc = cursec->curpc;
        
       -        cursec->curpc += siz;
       -        cursec->pc += siz;
       +        cursec->curpc += nbytes;
       +        cursec->pc += nbytes;
        
                if (pass == 2)
                        return;
        
       -        if (cursec->pc > cursec->max)
       -                cursec->max = cursec->pc;
       +        siz =cursec->pc - cursec->base;
       +        if (siz > cursec->size)
       +                cursec->size = siz;
        
                if (pc > cursec->pc ||
                    curpc > cursec->curpc ||
       @@ -211,6 +233,40 @@ secflags(char *attr)
        }
        
        Section *
       +secindex(int n)
       +{
       +        struct lsection *lp;
       +
       +        for (lp = seclist; lp && lp->s.index != n; lp = lp->next)
       +                ;
       +
       +        return (lp) ? &lp->s : NULL;
       +}
       +
       +static Section *
       +newsect(Symbol *sym)
       +{
       +        Section *sec;
       +        struct lsection *lp;
       +        static int index;
       +
       +        lp = xmalloc(sizeof(*lp));
       +        lp->next = seclist;
       +        seclist = lp;
       +
       +        sec = &lp->s;
       +        sec->mem = NULL;
       +        sec->name = xstrdup(sym->name);
       +        sec->base = sec->size = sec->pc = sec->curpc = 0;
       +        sec->flags = 0;
       +        sec->fill = 0;
       +        sec->align = 0;
       +        sec->index = index++;
       +
       +        return sec;
       +}
       +
       +Section *
        setsec(char *name, char *attr)
        {
                Section *sec;
       @@ -221,19 +277,10 @@ setsec(char *name, char *attr)
                if (sym->flags & ~FSECT)
                        error("invalid section name '%s'", name);
        
       -        if ((sec = sym->section) == NULL) {
       -                sec = xmalloc(sizeof(*sec));
       -                sec->mem = NULL;
       -                sec->sym = sym;
       -                sec->base = sec->max = sec->pc = sec->curpc = 0;
       -                sec->next = seclist;
       -                sec->flags = 0;
       -                sec->fill = 0;
       -                sec->aligment = 0;
       -                sec->next = seclist;
       -                seclist = sec;
       -
       -                sym->section = sec;
       +        sec = secindex(sym->section);
       +        if (sec == NULL) {
       +                sec = newsect(sym);
       +                sym->section = sec->index;
                        sym->flags = FSECT;
                }
                sec->flags |= secflags(attr);
       @@ -254,17 +301,17 @@ void
        cleansecs(void)
        {
                Section *sec;
       -        TUINT siz;
       +        struct lsection *lp;
        
       -        for (sec = seclist; sec; sec = sec->next) {
       +        for (lp = seclist; lp; lp = lp->next) {
       +                sec = &lp->s;
                        sec->curpc = sec->pc = sec->base;
                        if (pass == 1 || sec->flags & SFILE)
                                continue;
        
       -                siz = sec->max - sec->base;
       -                if (siz > SIZE_MAX)
       +                if (sec->size > SIZE_MAX)
                                die("as: out of memory");
       -                sec->mem = xmalloc(sec->max - sec->base);
       +                sec->mem = xmalloc(sec->size);
                }
                cursec = stext;
        }
       @@ -288,7 +335,7 @@ tmpsym(TUINT val)
                        tmpalloc = alloc(sizeof(*sym), NALLOC);
                sym = new(tmpalloc);
                sym->value = val;
       -        sym->section = NULL;
       +        sym->section = -1;
                sym->flags = FABS;
        
                return sym;
       @@ -302,3 +349,16 @@ killtmp(void)
                dealloc(tmpalloc);
                tmpalloc = NULL;
        }
       +
       +int
       +forallsecs(int (*fn)(Section *, void *), void *arg)
       +{
       +        struct lsection *lp;
       +
       +        for (lp = seclist; lp; lp = lp->next) {
       +                if ((*fn)(&lp->s, arg) < 0)
       +                        return -1;
       +        }
       +
       +        return 0;
       +}
 (DIR) diff --git a/src/libmach/libmach.h b/src/libmach/libmach.h
       @@ -53,7 +53,6 @@ struct objops {
                int (*getidx)(long *nsyms, char ***names, long **offset, FILE *fp);
        };
        
       -
        struct map {
                int n;
                struct mapsec {