static struct SAA *elf_build_reltab(long *len, struct Reloc *r) { struct SAA *s; unsigned char *p, entry[8]; if (!r) return NULL; s = saa_init(1L); *len = 0; while (r) { long sym = r->symbol; if (sym >= GLOBAL_TEMP_BASE) sym += -GLOBAL_TEMP_BASE + (nsects + 3) + nlocals; p = entry; WRITELONG(p, r->address); WRITELONG(p, (sym << 8) + r->type); saa_wbytes(s, entry, 8L); *len += 8; r = r->next; } return s; }
/* * Writes a string, *including* the final null, to the specified SAA, * and return the number of bytes written. */ size_t saa_wcstring(struct SAA *s, const char *str) { size_t bytes = strlen(str) + 1; saa_wbytes(s, str, bytes); return bytes; }
static void coff_deflabel (char *name, long segment, long offset, int is_global, char *special) { int pos = strslen+4; struct Symbol *sym; if (special) error (ERR_NONFATAL, "binary format does not support any" " special symbol types"); if (name[0] == '.' && name[1] == '.' && name[2] != '@') { error (ERR_NONFATAL, "unrecognised special symbol `%s'", name); return; } if (strlen(name) > 8) { saa_wbytes (strs, name, (long)(1+strlen(name))); strslen += 1+strlen(name); } else pos = -1; sym = saa_wstruct (syms); sym->strpos = pos; if (pos == -1) strcpy (sym->name, name); sym->is_global = !!is_global; if (segment == NO_SEG) sym->section = -1; /* absolute symbol */ else { int i; sym->section = 0; for (i=0; i<nsects; i++) if (segment == sects[i]->index) { sym->section = i+1; break; } if (!sym->section) sym->is_global = TRUE; } if (is_global == 2) sym->value = offset; else sym->value = (sym->section == 0 ? 0 : offset); /* * define the references from external-symbol segment numbers * to these symbol records. */ if (sym->section == 0) bsym = raa_write (bsym, segment, nsyms); if (segment != NO_SEG) symval = raa_write (symval, segment, sym->section ? 0 : sym->value); nsyms++; }
static int as86_add_string (char *name) { int pos = strslen; int length = strlen(name); saa_wbytes (strs, name, (long)(length+1)); strslen += 1+length; return pos; }
static size_t as86_add_string(const char *name) { size_t pos = strslen; size_t length = strlen(name); saa_wbytes(strs, name, length + 1); strslen += 1 + length; return pos; }
static void elf_init(FILE * fp, efunc errfunc, ldfunc ldef, evalfunc eval) { elffp = fp; error = errfunc; evaluate = eval; (void)ldef; /* placate optimisers */ sects = NULL; nsects = sectlen = 0; syms = saa_init((long)sizeof(struct Symbol)); nlocals = nglobs = 0; bsym = raa_init(); strs = saa_init(1L); saa_wbytes(strs, "\0", 1L); saa_wbytes(strs, elf_module, (long)(strlen(elf_module) + 1)); strslen = 2 + strlen(elf_module); shstrtab = NULL; shstrtablen = shstrtabsize = 0;; add_sectname("", ""); fwds = NULL; elf_gotpc_sect = seg_alloc(); ldef("..gotpc", elf_gotpc_sect + 1, 0L, NULL, FALSE, FALSE, &of_elf, error); elf_gotoff_sect = seg_alloc(); ldef("..gotoff", elf_gotoff_sect + 1, 0L, NULL, FALSE, FALSE, &of_elf, error); elf_got_sect = seg_alloc(); ldef("..got", elf_got_sect + 1, 0L, NULL, FALSE, FALSE, &of_elf, error); elf_plt_sect = seg_alloc(); ldef("..plt", elf_plt_sect + 1, 0L, NULL, FALSE, FALSE, &of_elf, error); elf_sym_sect = seg_alloc(); ldef("..sym", elf_sym_sect + 1, 0L, NULL, FALSE, FALSE, &of_elf, error); def_seg = seg_alloc(); }
static void elf_deflabel(char *name, long segment, long offset, int is_global, char *special) { int pos = strslen; struct Symbol *sym; int special_used = FALSE; #if defined(DEBUG) && DEBUG>2 fprintf(stderr, " elf_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n", name, segment, offset, is_global, special); #endif if (name[0] == '.' && name[1] == '.' && name[2] != '@') { /* * This is a NASM special symbol. We never allow it into * the ELF symbol table, even if it's a valid one. If it * _isn't_ a valid one, we should barf immediately. */ if (strcmp(name, "..gotpc") && strcmp(name, "..gotoff") && strcmp(name, "..got") && strcmp(name, "..plt") && strcmp(name, "..sym")) error(ERR_NONFATAL, "unrecognised special symbol `%s'", name); return; } if (is_global == 3) { struct Symbol **s; /* * Fix up a forward-reference symbol size from the first * pass. */ for (s = &fwds; *s; s = &(*s)->nextfwd) if (!strcmp((*s)->name, name)) { struct tokenval tokval; expr *e; char *p = special; while (*p && !isspace(*p)) p++; while (*p && isspace(*p)) p++; stdscan_reset(); stdscan_bufptr = p; tokval.t_type = TOKEN_INVALID; e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL); if (e) { if (!is_simple(e)) error(ERR_NONFATAL, "cannot use relocatable" " expression as symbol size"); else (*s)->size = reloc_value(e); } /* * Remove it from the list of unresolved sizes. */ nasm_free((*s)->name); *s = (*s)->nextfwd; return; } return; /* it wasn't an important one */ } saa_wbytes(strs, name, (long)(1 + strlen(name))); strslen += 1 + strlen(name); sym = saa_wstruct(syms); sym->strpos = pos; sym->type = is_global ? SYM_GLOBAL : 0; sym->size = 0; if (segment == NO_SEG) sym->section = SHN_ABS; else { int i; sym->section = SHN_UNDEF; if (nsects == 0 && segment == def_seg) { int tempint; if (segment != elf_section_names(".text", 2, &tempint)) error(ERR_PANIC, "strange segment conditions in ELF driver"); sym->section = nsects; } else { for (i = 0; i < nsects; i++) if (segment == sects[i]->index) { sym->section = i + 1; break; } } } if (is_global == 2) { sym->size = offset; sym->value = 0; sym->section = SHN_COMMON; /* * We have a common variable. Check the special text to see * if it's a valid number and power of two; if so, store it * as the alignment for the common variable. */ if (special) { int err; sym->value = readnum(special, &err); if (err) error(ERR_NONFATAL, "alignment constraint `%s' is not a" " valid number", special); else if ((sym->value | (sym->value - 1)) != 2 * sym->value - 1) error(ERR_NONFATAL, "alignment constraint `%s' is not a" " power of two", special); } special_used = TRUE; } else sym->value = (sym->section == SHN_UNDEF ? 0 : offset); if (sym->type == SYM_GLOBAL) { /* * There's a problem here that needs fixing. * If sym->section == SHN_ABS, then the first line of the * else section causes a core dump, because its a reference * beyond the end of the section array. * This behaviour is exhibited by this code: * GLOBAL crash_nasm * crash_nasm equ 0 * * I'm not sure how to procede, because I haven't got the * first clue about how ELF works, so I don't know what to * do with it. Furthermore, I'm not sure what the rest of this * section of code does. Help? * * For now, I'll see if doing absolutely nothing with it will * work... */ if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON) { bsym = raa_write(bsym, segment, nglobs); } else if (sym->section != SHN_ABS) { /* * This is a global symbol; so we must add it to the linked * list of global symbols in its section. We'll push it on * the beginning of the list, because it doesn't matter * much which end we put it on and it's easier like this. * * In addition, we check the special text for symbol * type and size information. */ sym->next = sects[sym->section - 1]->gsyms; sects[sym->section - 1]->gsyms = sym; if (special) { int n = strcspn(special, " "); if (!nasm_strnicmp(special, "function", n)) sym->type |= SYM_FUNCTION; else if (!nasm_strnicmp(special, "data", n) || !nasm_strnicmp(special, "object", n)) sym->type |= SYM_DATA; else error(ERR_NONFATAL, "unrecognised symbol type `%.*s'", n, special); if (special[n]) { struct tokenval tokval; expr *e; int fwd = FALSE; char *saveme = stdscan_bufptr; /* bugfix? fbk 8/10/00 */ while (special[n] && isspace(special[n])) n++; /* * We have a size expression; attempt to * evaluate it. */ stdscan_reset(); stdscan_bufptr = special + n; tokval.t_type = TOKEN_INVALID; e = evaluate(stdscan, NULL, &tokval, &fwd, 0, error, NULL); if (fwd) { sym->nextfwd = fwds; fwds = sym; sym->name = nasm_strdup(name); } else if (e) { if (!is_simple(e)) error(ERR_NONFATAL, "cannot use relocatable" " expression as symbol size"); else sym->size = reloc_value(e); } stdscan_bufptr = saveme; /* bugfix? fbk 8/10/00 */ } special_used = TRUE; } } sym->globnum = nglobs; nglobs++; } else nlocals++; if (special && !special_used) error(ERR_NONFATAL, "no special symbol features supported here"); }
static void elf_sect_write(struct Section *sect, const unsigned char *data, unsigned long len) { saa_wbytes(sect->data, data, len); sect->len += len; }
static struct SAA *elf_build_symtab(long *len, long *local) { struct SAA *s = saa_init(1L); struct Symbol *sym; unsigned char entry[16], *p; int i; *len = *local = 0; /* * First, an all-zeros entry, required by the ELF spec. */ saa_wbytes(s, NULL, 16L); /* null symbol table entry */ *len += 16; (*local)++; /* * Next, an entry for the file name. */ p = entry; WRITELONG(p, 1); /* we know it's 1st thing in strtab */ WRITELONG(p, 0); /* no value */ WRITELONG(p, 0); /* no size either */ WRITESHORT(p, 4); /* type FILE */ WRITESHORT(p, SHN_ABS); saa_wbytes(s, entry, 16L); *len += 16; (*local)++; /* * Now some standard symbols defining the segments, for relocation * purposes. */ for (i = 1; i <= nsects + 1; i++) { p = entry; WRITELONG(p, 0); /* no symbol name */ WRITELONG(p, 0); /* offset zero */ WRITELONG(p, 0); /* size zero */ WRITESHORT(p, 3); /* local section-type thing */ WRITESHORT(p, (i == 1 ? SHN_ABS : i - 1)); /* the section id */ saa_wbytes(s, entry, 16L); *len += 16; (*local)++; } /* * Now the other local symbols. */ saa_rewind(syms); while ((sym = saa_rstruct(syms))) { if (sym->type & SYM_GLOBAL) continue; p = entry; WRITELONG(p, sym->strpos); WRITELONG(p, sym->value); WRITELONG(p, sym->size); WRITESHORT(p, sym->type); /* local non-typed thing */ WRITESHORT(p, sym->section); saa_wbytes(s, entry, 16L); *len += 16; (*local)++; } /* * Now the global symbols. */ saa_rewind(syms); while ((sym = saa_rstruct(syms))) { if (!(sym->type & SYM_GLOBAL)) continue; p = entry; WRITELONG(p, sym->strpos); WRITELONG(p, sym->value); WRITELONG(p, sym->size); WRITESHORT(p, sym->type); /* global non-typed thing */ WRITESHORT(p, sym->section); saa_wbytes(s, entry, 16L); *len += 16; } return s; }
static void aout_deflabel (char *name, long segment, long offset, int is_global, char *special) { int pos = strslen+4; struct Symbol *sym; int special_used = FALSE; if (name[0] == '.' && name[1] == '.' && name[2] != '@') { /* * This is a NASM special symbol. We never allow it into * the a.out symbol table, even if it's a valid one. If it * _isn't_ a valid one, we should barf immediately. */ if (strcmp(name, "..gotpc") && strcmp(name, "..gotoff") && strcmp(name, "..got") && strcmp(name, "..plt") && strcmp(name, "..sym")) error (ERR_NONFATAL, "unrecognised special symbol `%s'", name); return; } if (is_global == 3) { struct Symbol **s; /* * Fix up a forward-reference symbol size from the first * pass. */ for (s = &fwds; *s; s = &(*s)->nextfwd) if (!strcmp((*s)->name, name)) { struct tokenval tokval; expr *e; char *p = special; while (*p && !isspace(*p)) p++; while (*p && isspace(*p)) p++; stdscan_reset(); stdscan_bufptr = p; tokval.t_type = TOKEN_INVALID; e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL); if (e) { if (!is_simple(e)) error (ERR_NONFATAL, "cannot use relocatable" " expression as symbol size"); else (*s)->size = reloc_value(e); } /* * Remove it from the list of unresolved sizes. */ nasm_free ((*s)->name); *s = (*s)->nextfwd; return; } return; /* it wasn't an important one */ } saa_wbytes (strs, name, (long)(1+strlen(name))); strslen += 1+strlen(name); sym = saa_wstruct (syms); sym->strpos = pos; sym->type = is_global ? SYM_GLOBAL : 0; sym->segment = segment; if (segment == NO_SEG) sym->type |= SECT_ABS; else if (segment == stext.index) { sym->type |= SECT_TEXT; if (is_global) { sym->next = stext.gsyms; stext.gsyms = sym; } else if (!stext.asym) stext.asym = sym; } else if (segment == sdata.index) { sym->type |= SECT_DATA; if (is_global) { sym->next = sdata.gsyms; sdata.gsyms = sym; } else if (!sdata.asym) sdata.asym = sym; } else if (segment == sbss.index) { sym->type |= SECT_BSS; if (is_global) { sym->next = sbss.gsyms; sbss.gsyms = sym; } else if (!sbss.asym) sbss.asym = sym; } else sym->type = SYM_GLOBAL; if (is_global == 2) sym->value = offset; else sym->value = (sym->type == SYM_GLOBAL ? 0 : offset); if (is_global && sym->type != SYM_GLOBAL) { /* * Global symbol exported _from_ this module. We must check * the special text for type information. */ if (special) { int n = strcspn(special, " "); if (!nasm_strnicmp(special, "function", n)) sym->type |= SYM_FUNCTION; else if (!nasm_strnicmp(special, "data", n) || !nasm_strnicmp(special, "object", n)) sym->type |= SYM_DATA; else error(ERR_NONFATAL, "unrecognised symbol type `%.*s'", n, special); if (special[n]) { struct tokenval tokval; expr *e; int fwd = FALSE; char *saveme=stdscan_bufptr; /* bugfix? fbk 8/10/00 */ if (!bsd) { error(ERR_NONFATAL, "Linux a.out does not support" " symbol size information"); } else { while (special[n] && isspace(special[n])) n++; /* * We have a size expression; attempt to * evaluate it. */ sym->type |= SYM_WITH_SIZE; stdscan_reset(); stdscan_bufptr = special+n; tokval.t_type = TOKEN_INVALID; e = evaluate(stdscan, NULL, &tokval, &fwd, 0, error, NULL); if (fwd) { sym->nextfwd = fwds; fwds = sym; sym->name = nasm_strdup(name); } else if (e) { if (!is_simple(e)) error (ERR_NONFATAL, "cannot use relocatable" " expression as symbol size"); else sym->size = reloc_value(e); } } stdscan_bufptr=saveme; /* bugfix? fbk 8/10/00 */ } special_used = TRUE; } } /* * define the references from external-symbol segment numbers * to these symbol records. */ if (segment != NO_SEG && segment != stext.index && segment != sdata.index && segment != sbss.index) bsym = raa_write (bsym, segment, nsyms); sym->symnum = nsyms; nsyms++; if (sym->type & SYM_WITH_SIZE) nsyms++; /* and another for the size */ if (special && !special_used) error(ERR_NONFATAL, "no special symbol features supported here"); }
static void as86_sect_write(struct Section *sect, const uint8_t *data, uint32_t len) { saa_wbytes(sect->data, data, len); sect->datalen += len; }
static void as86_sect_write (struct Section *sect, unsigned char *data, unsigned long len) { saa_wbytes (sect->data, data, len); sect->datalen += len; }