aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-09 22:05:15 +1300
committerAndrew Chambers <[email protected]>2021-10-09 22:05:15 +1300
commitc726740a3882ebdc85c0d06c922dfaf5c6532c69 (patch)
tree78e74a25dd09238ef4967cea29c150af2215d6dd
parenta439d4004379cc73dd6b2bf330130733396f9d61 (diff)
Add section directive.
-rw-r--r--asm.peg22
-rw-r--r--main.c39
-rw-r--r--minias.h12
3 files changed, 70 insertions, 3 deletions
diff --git a/asm.peg b/asm.peg
index 2251966..4b1828e 100644
--- a/asm.peg
+++ b/asm.peg
@@ -8,11 +8,11 @@ ws = [ \t]+
eol = ws? "\n"
stmt =
- d:directive {$$ = d;}
+ '.' d:directive {$$ = d;}
| i:instr { $$ = i; }
| l:label { $$ = l; }
-directive = '.' (
+directive =
"glob" 'o'? 'l' ws i:ident
{ $$.globl = (Globl){.kind = ASM_DIR_GLOBL, .name = i.ident.name }; }
| "ascii" <'z'?> ws s:string
@@ -25,7 +25,23 @@ directive = '.' (
{ $$.balign = (Balign){.kind = ASM_DIR_BALIGN, .align = n.number.v }; }
| "byte" ws n:number
{ $$.byte = (Byte){.kind = ASM_DIR_BYTE, .b = (uint8_t)n.number.v }; }
-)
+ | sd:section-directive { $$ = sd; }
+
+section-directive =
+ "section" ws? n:section-name (
+ ws? ',' ws? f:section-flags ws? ',' ws? t:section-type
+ {$$.section = (DirSection){.kind=ASM_DIR_SECTION, .name=n.charptr, .flags=f.charptr, .type=t.i64}; }
+ | ws? ',' ws? f:section-flags
+ {$$.section = (DirSection){.kind=ASM_DIR_SECTION, .name=n.charptr, .flags=f.charptr, .type=SHT_PROGBITS}; }
+ |
+ {$$.section = (DirSection){.kind=ASM_DIR_SECTION, .name=n.charptr, .flags="", .type=SHT_PROGBITS}; }
+ )
+
+section-name = <[.a-zA-Z0-9\-]+> { $$.charptr = xstrdup(yytext); }
+section-flags = '"' <[awx]*> '"' { $$.charptr = xstrdup(yytext); }
+section-type =
+ "@nobits" { $$.i64 = SHT_NOBITS; }
+ | "@progbits" { $$.i64 = SHT_PROGBITS; }
label =
i:ident ':'
diff --git a/main.c b/main.c
index 5914994..8e3da68 100644
--- a/main.c
+++ b/main.c
@@ -78,6 +78,19 @@ static Section *newsection() {
return s;
}
+static Section *getsection(const char *name) {
+ size_t i;
+ Section *s;
+
+ for (i = 0; i < nsections; i++) {
+ if (strcmp(secname(&sections[i]), name) == 0)
+ return &sections[i];
+ }
+ s = newsection();
+ s->hdr.sh_name = elfstr(shstrtab, name);
+ return s;
+}
+
static void initsections(void) {
Elf64_Sym elfsym;
@@ -530,6 +543,32 @@ static void assemble(void) {
sym = getsym(v->globl.name);
sym->global = 1;
break;
+ case ASM_DIR_SECTION: {
+ size_t i;
+ const char *fp;
+ Section *s;
+
+ s = getsection(v->section.name);
+ s->hdr.sh_type = v->section.type;
+ fp = v->section.flags;
+ while (fp && *fp) {
+ switch (*(fp++)) {
+ case 'a':
+ s->hdr.sh_flags |= SHF_ALLOC;
+ break;
+ case 'w':
+ s->hdr.sh_flags |= SHF_WRITE;
+ break;
+ case 'x':
+ s->hdr.sh_flags |= SHF_EXECINSTR;
+ break;
+ default:
+ unreachable();
+ }
+ }
+ cursection = s;
+ break;
+ }
case ASM_DIR_DATA:
cursection = data;
break;
diff --git a/minias.h b/minias.h
index 68df579..78d478a 100644
--- a/minias.h
+++ b/minias.h
@@ -49,6 +49,7 @@ typedef enum {
ASM_MEMARG,
// Directives
ASM_DIR_GLOBL,
+ ASM_DIR_SECTION,
ASM_DIR_ASCII,
ASM_DIR_ASCIIZ,
ASM_DIR_DATA,
@@ -164,6 +165,13 @@ typedef struct {
typedef struct {
AsmKind kind;
+ const char *name;
+ const char *flags;
+ int type;
+} DirSection;
+
+typedef struct {
+ AsmKind kind;
uint8_t b;
} Byte;
@@ -231,6 +239,7 @@ union Parsev {
AsmKind kind;
Label label;
Globl globl;
+ DirSection section;
Balign balign;
Ascii ascii;
Asciiz asciiz;
@@ -244,6 +253,9 @@ union Parsev {
Ident ident;
Number number;
String string;
+ // Temporary values.
+ const char *charptr;
+ int64_t i64;
};
typedef struct AsmLine AsmLine;