diff options
| author | Andrew Chambers <[email protected]> | 2021-10-24 14:34:23 +1300 |
|---|---|---|
| committer | Andrew Chambers <[email protected]> | 2021-10-24 14:34:37 +1300 |
| commit | cd21b90feaa9b66296b8614023349fae7d314b4b (patch) | |
| tree | 198930320598fa39505d955f8ba3f8c927418689 | |
| parent | 0d53c9d7b78aec53922bd0d57dbe48db27570506 (diff) | |
Weak symbols.
| -rw-r--r-- | asm.peg | 2 | ||||
| -rw-r--r-- | main.c | 31 | ||||
| -rw-r--r-- | minias.h | 10 | ||||
| -rw-r--r-- | parse.c | 4 | ||||
| -rw-r--r-- | test/execute/0003-weaksym.s | 12 |
5 files changed, 39 insertions, 20 deletions
@@ -35,6 +35,8 @@ directive = { $$.dirquad = (Quad){.kind = ASM_DIR_QUAD, .value = v.value }; } | "set" ws s:ident ws? ',' ws? v:value { $$.set = (Set){.kind = ASM_DIR_SET, .sym = s.charptr, .value = v.value }; } + | "weak" ws s:ident + { $$.weak = (Weak){.kind = ASM_DIR_WEAK, .sym = s.charptr}; } | fd:fill-directive { $$ = fd; } | sd:section-directive @@ -55,6 +55,8 @@ getsym(const char *name) **ps = (Symbol) { .name = name, .wco = -1, + .bind = STB_LOCAL, + .type = STT_NOTYPE, }; } s = *ps; @@ -716,7 +718,11 @@ assemble(void) break; case ASM_DIR_GLOBL: sym = getsym(v->globl.name); - sym->global = 1; + sym->bind = STB_GLOBAL; + break; + case ASM_DIR_WEAK: + sym = getsym(v->weak.sym); + sym->bind = STB_WEAK; break; case ASM_DIR_SECTION: { const char *fp; @@ -857,16 +863,16 @@ relaxreset(void) /* Try to resolve the address of a symbol, this will recursively look for the symbol address if it is defined relative to another symbol. */ static int -resolvesymrecurse(Symbol *sym, int n) +resolvesym2(Symbol *sym, int depth) { Symbol *indirect; - if (n > 64) + if (depth > 64) fatal("recursion limit hit when resolving symbol location"); if (sym->value.l) { indirect = getsym(sym->value.l); - if (!resolvesymrecurse(indirect, n + 1)) + if (!resolvesym2(indirect, depth + 1)) return 0; sym->section = indirect->section; sym->value.l = NULL; @@ -885,7 +891,7 @@ resolvesymrecurse(Symbol *sym, int n) static int resolvesym(Symbol *sym) { - return resolvesymrecurse(sym, 0); + return resolvesym2(sym, 0); } /* Resolve all symbols to their final location if we can. */ @@ -905,22 +911,13 @@ static void addtosymtab(Symbol *sym) { Elf64_Sym elfsym; - int stype; - int sbind; - - stype = 0; - if (sym->defined) { - sbind = sym->global ? STB_GLOBAL : STB_LOCAL; - } else { - sbind = STB_GLOBAL; - } sym->idx = symtab->hdr.sh_size / symtab->hdr.sh_entsize; elfsym.st_name = elfstr(strtab, sym->name); elfsym.st_value = sym->value.c; elfsym.st_size = sym->size; - elfsym.st_info = ELF64_ST_INFO(sbind, stype); + elfsym.st_info = ELF64_ST_INFO(sym->bind, sym->type); elfsym.st_shndx = sym->section ? sym->section->idx : SHN_UNDEF; elfsym.st_other = 0; secaddbytes(symtab, &elfsym, sizeof(Elf64_Sym)); @@ -937,7 +934,7 @@ fillsymtab(void) if (!symbols->keys[i].str) continue; sym = symbols->vals[i]; - if (!sym->defined || sym->global) + if (sym->bind != STB_LOCAL) continue; addtosymtab(sym); } @@ -951,7 +948,7 @@ fillsymtab(void) continue; sym = symbols->vals[i]; - if (sym->defined && !sym->global) + if (sym->bind == STB_LOCAL) continue; addtosymtab(sym); } @@ -31,7 +31,8 @@ typedef struct { Value value; int64_t wco; /* worst case offset */ int64_t size; - int global; + int bind; /* STB_GLOBAL, STB_LOCAL, STB_WEAK */ + int type; int defined; Section *section; } Symbol; @@ -54,6 +55,7 @@ typedef enum { ASM_MEMARG, // Directives. ASM_DIR_GLOBL, + ASM_DIR_WEAK, ASM_DIR_SECTION, ASM_DIR_ASCII, ASM_DIR_ASCIIZ, @@ -182,6 +184,11 @@ typedef struct Set { Value value; } Set; +typedef struct Weak { + AsmKind kind; + const char *sym; +} Weak; + typedef struct DirSection { AsmKind kind; int32_t type; @@ -306,6 +313,7 @@ union Parsev { Jmp jmp; Fill fill; Set set; + Weak weak; Byte dirbyte; Short dirshort; Int dirint; @@ -75,9 +75,9 @@ decodestring(char *s) c = '\\'; } else { for (i = 0; i < 3 && *s >= '0' && *s <= '7'; i++, s++) - c = c * 8 + (*s - '0'); + c = c * 8 + (*s - '0'); if (i == 0) - unreachable(); + unreachable(); s--; } } else { diff --git a/test/execute/0003-weaksym.s b/test/execute/0003-weaksym.s new file mode 100644 index 0000000..f6c12ce --- /dev/null +++ b/test/execute/0003-weaksym.s @@ -0,0 +1,12 @@ +.data +.weak foo +foo: + .quad 0 + +.text +.globl main +main: + movq foo(%rip), %rax + ret + +.section .note.GNU-stack,"",@progbits |
