aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm.peg2
-rw-r--r--main.c31
-rw-r--r--minias.h10
-rw-r--r--parse.c4
-rw-r--r--test/execute/0003-weaksym.s12
5 files changed, 39 insertions, 20 deletions
diff --git a/asm.peg b/asm.peg
index 596852b..bbc00f1 100644
--- a/asm.peg
+++ b/asm.peg
@@ -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
diff --git a/main.c b/main.c
index 38ad138..56df5b5 100644
--- a/main.c
+++ b/main.c
@@ -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);
}
diff --git a/minias.h b/minias.h
index ccef65b..3e4f225 100644
--- a/minias.h
+++ b/minias.h
@@ -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;
diff --git a/parse.c b/parse.c
index 9e955f7..5c2f5cb 100644
--- a/parse.c
+++ b/parse.c
@@ -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