const struct ofmt *ofmt_find(const char *name, const struct ofmt_alias **ofmt_alias) { const struct ofmt * const *ofp; const struct ofmt *of; unsigned int i; *ofmt_alias = NULL; /* primary targets first */ for (ofp = drivers; (of = *ofp); ofp++) { if (!nasm_stricmp(name, of->shortname)) return of; } /* lets walk thru aliases then */ for (i = 0; i < ARRAY_SIZE(ofmt_aliases); i++) { if (ofmt_aliases[i].shortname && !nasm_stricmp(name, ofmt_aliases[i].shortname)) { *ofmt_alias = &ofmt_aliases[i]; return ofmt_aliases[i].ofmt; } } return NULL; }
/* parse section attributes */ void section_attrib(char *name, char *attr, int pass, uint32_t *flags_and, uint32_t *flags_or, uint64_t *align, int *type) { char *opt, *val, *next; opt = nasm_skip_spaces(attr); if (!opt || !*opt) return; while ((opt = nasm_opt_val(opt, &val, &next))) { if (!nasm_stricmp(opt, "align")) { *align = atoi(val); if (*align == 0) { *align = SHA_ANY; } else if (!is_power2(*align)) { nasm_error(ERR_NONFATAL, "section alignment %"PRId64" is not a power of two", *align); *align = SHA_ANY; } } else if (!nasm_stricmp(opt, "alloc")) { *flags_and |= SHF_ALLOC; *flags_or |= SHF_ALLOC; } else if (!nasm_stricmp(opt, "noalloc")) { *flags_and |= SHF_ALLOC; *flags_or &= ~SHF_ALLOC; } else if (!nasm_stricmp(opt, "exec")) { *flags_and |= SHF_EXECINSTR; *flags_or |= SHF_EXECINSTR; } else if (!nasm_stricmp(opt, "noexec")) { *flags_and |= SHF_EXECINSTR; *flags_or &= ~SHF_EXECINSTR; } else if (!nasm_stricmp(opt, "write")) { *flags_and |= SHF_WRITE; *flags_or |= SHF_WRITE; } else if (!nasm_stricmp(opt, "tls")) { *flags_and |= SHF_TLS; *flags_or |= SHF_TLS; } else if (!nasm_stricmp(opt, "nowrite")) { *flags_and |= SHF_WRITE; *flags_or &= ~SHF_WRITE; } else if (!nasm_stricmp(opt, "progbits")) { *type = SHT_PROGBITS; } else if (!nasm_stricmp(opt, "nobits")) { *type = SHT_NOBITS; } else if (pass == 1) { nasm_error(ERR_WARNING, "Unknown section attribute '%s' ignored on" " declaration of section `%s'", opt, name); } opt = next; } }
const unsigned char *nasm_stdmac_find_package(const char *package) { static const struct { const char *package; const unsigned char *macros; } packages[2] = { { "altreg", nasm_stdmac_altreg }, { "smartalign", nasm_stdmac_smartalign }, }; #define UNUSED 16383 static const int16_t hash1[2] = { 0, -1, }; static const int16_t hash2[2] = { 1, UNUSED, }; uint32_t k1, k2; uint64_t crc; uint16_t ix; crc = crc64i(UINT64_C(0x076259c3e291c26c), package); k1 = (uint32_t)crc; k2 = (uint32_t)(crc >> 32); ix = hash1[k1 & 0x1] + hash2[k2 & 0x1]; if (ix >= 2) return NULL; if (nasm_stricmp(packages[ix].package, package)) return NULL; return packages[ix].macros; }
const struct dfmt *dfmt_find(const struct ofmt *ofmt, const char *name) { const struct dfmt * const *dfp; const struct dfmt *df; for (dfp = ofmt->debug_formats; (df = *dfp); dfp++) { if (!nasm_stricmp(name, df->shortname)) return df; } return NULL; }
int bsii(const char *string, const char **array, int size) { int i = -1, j = size; /* always, i < index < j */ while (j - i >= 2) { int k = (i + j) / 2; int l = nasm_stricmp(string, array[k]); if (l < 0) /* it's in the first half */ j = k; else if (l > 0) /* it's in the second half */ i = k; else /* we've got it :) */ return k; } return -1; /* we haven't got it :( */ }
/* * because this routine is not bracketed in * the main program, this routine will be called even if there * is no request for debug info * so, we have to make sure the ??LINE segment is avaialbe * as the first segment when this debug format is selected */ static void dbgls_linnum(const char *lnfname, int32_t lineno, int32_t segto) { struct FileName *fn; struct ieeeSection *seg; int i = 0; if (segto == NO_SEG) return; /* * If `any_segs' is still false, we must define a default * segment. */ if (!any_segs) { int tempint; /* ignored */ if (segto != ieee_segment("__NASMDEFSEG", 2, &tempint)) nasm_error(ERR_PANIC, "strange segment conditions in OBJ driver"); } /* * Find the segment we are targetting. */ for (seg = seghead; seg; seg = seg->next) if (seg->index == segto) break; if (!seg) nasm_error(ERR_PANIC, "lineno directed to nonexistent segment?"); for (fn = fnhead; fn; fn = fn->next) { if (!nasm_stricmp(lnfname, fn->name)) break; i++; } if (!fn) { fn = nasm_malloc(sizeof(*fn)); fn->name = nasm_malloc(strlen(lnfname) + 1); fn->index = i; strcpy(fn->name, lnfname); fn->next = NULL; *fntail = fn; fntail = &fn->next; } ieee_write_byte(seghead, fn->index); ieee_write_word(seghead, lineno); ieee_write_fixup(segto, NO_SEG, seghead, 4, OUT_ADDRESS, seg->currentpos); }
static bool declare_label_lptr(union label *lptr, enum label_type type, const char *special) { if (special && !special[0]) special = NULL; if (lptr->defn.type == type || (pass0 == 0 && lptr->defn.type == LBL_LOCAL)) { lptr->defn.type = type; if (special) { if (!lptr->defn.special) lptr->defn.special = perm_copy(special); else if (nasm_stricmp(lptr->defn.special, special)) nasm_error(ERR_NONFATAL, "symbol `%s' has inconsistent attributes `%s' and `%s'", lptr->defn.label, lptr->defn.special, special); } return true; } /* EXTERN can be replaced with GLOBAL or COMMON */ if (lptr->defn.type == LBL_EXTERN && (type == LBL_GLOBAL || type == LBL_COMMON)) { lptr->defn.type = type; /* Override special unconditionally */ if (special) lptr->defn.special = perm_copy(special); return true; } /* GLOBAL or COMMON ignore subsequent EXTERN */ if ((lptr->defn.type == LBL_GLOBAL || lptr->defn.type == LBL_COMMON) && type == LBL_EXTERN) { if (!lptr->defn.special) lptr->defn.special = perm_copy(special); return false; /* Don't call define_label() after this! */ } nasm_error(ERR_NONFATAL, "symbol `%s' declared both as %s and %s", lptr->defn.label, types[lptr->defn.type], types[type]); return false; }
enum preproc_token pp_token_hash(const char *token) { #define UNUSED 16383 static const int16_t hash1[128] = { UNUSED, UNUSED, 0, 0, 0, 0, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 0, UNUSED, UNUSED, 0, 0, UNUSED, 0, UNUSED, UNUSED, UNUSED, 0, -45, UNUSED, 0, UNUSED, -60, 0, UNUSED, UNUSED, -42, UNUSED, UNUSED, -49, UNUSED, UNUSED, 0, UNUSED, UNUSED, 0, UNUSED, UNUSED, UNUSED, 48, UNUSED, UNUSED, 49, 5, UNUSED, -52, 65, UNUSED, UNUSED, 0, 0, UNUSED, 38, UNUSED, 30, 0, UNUSED, 6, 35, UNUSED, UNUSED, 60, 34, UNUSED, 134, UNUSED, -86, -11, 41, 17, 0, 129, -84, UNUSED, UNUSED, 82, 0, UNUSED, 16, 97, -65, -100, 0, -10, -76, UNUSED, UNUSED, UNUSED, 1, UNUSED, 0, 12, UNUSED, -145, 41, 105, UNUSED, 84, UNUSED, 43, 85, UNUSED, 22, 0, -13, UNUSED, UNUSED, 77, -2, UNUSED, UNUSED, 11, 91, -6, UNUSED, UNUSED, UNUSED, UNUSED, 106, 44, UNUSED, }; static const int16_t hash2[128] = { UNUSED, 0, UNUSED, 0, UNUSED, UNUSED, 0, UNUSED, UNUSED, 0, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 0, 80, 0, 64, UNUSED, 0, 0, 0, 0, UNUSED, UNUSED, UNUSED, 64, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 0, 121, 0, UNUSED, 21, 99, 63, UNUSED, 114, UNUSED, 178, UNUSED, UNUSED, UNUSED, 0, UNUSED, -39, UNUSED, 88, UNUSED, UNUSED, UNUSED, UNUSED, 87, UNUSED, 42, UNUSED, UNUSED, 141, UNUSED, UNUSED, UNUSED, 102, UNUSED, 46, 105, 149, UNUSED, 23, 53, 0, UNUSED, UNUSED, UNUSED, 0, UNUSED, UNUSED, UNUSED, 33, 0, 0, 92, UNUSED, 50, 72, UNUSED, 7, 42, 65, UNUSED, UNUSED, 112, 52, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 98, 100, 71, UNUSED, 19, 63, 32, UNUSED, UNUSED, UNUSED, 96, 17, 84, 132, UNUSED, 37, UNUSED, 9, 20, UNUSED, UNUSED, 75, 97, UNUSED, }; uint32_t k1, k2; uint64_t crc; uint16_t ix; crc = crc64i(UINT64_C(0xaee7ac5ccabdec91), token); k1 = (uint32_t)crc; k2 = (uint32_t)(crc >> 32); ix = hash1[k1 & 0x7f] + hash2[k2 & 0x7f]; if (ix >= 108) return PP_INVALID; if (!pp_directives[ix] || nasm_stricmp(pp_directives[ix], token)) return PP_INVALID; return ix; }
/* * segment registry */ static int32_t ieee_segment(char *name, int pass, int *bits) { /* * We call the label manager here to define a name for the new * segment, and when our _own_ label-definition stub gets * called in return, it should register the new segment name * using the pointer it gets passed. That way we save memory, * by sponging off the label manager. */ if (!name) { *bits = 16; if (!any_segs) return 0; return seghead->index; } else { struct ieeeSection *seg; int ieee_idx, attrs; bool rn_error; char *p; /* * Look for segment attributes. */ attrs = 0; while (*name == '.') name++; /* hack, but a documented one */ p = name; while (*p && !nasm_isspace(*p)) p++; if (*p) { *p++ = '\0'; while (*p && nasm_isspace(*p)) *p++ = '\0'; } while (*p) { while (*p && !nasm_isspace(*p)) p++; if (*p) { *p++ = '\0'; while (*p && nasm_isspace(*p)) *p++ = '\0'; } attrs++; } ieee_idx = 1; for (seg = seghead; seg; seg = seg->next) { ieee_idx++; if (!strcmp(seg->name, name)) { if (attrs > 0 && pass == 1) nasm_error(ERR_WARNING, "segment attributes specified on" " redeclaration of segment: ignoring"); if (seg->use32) *bits = 32; else *bits = 16; return seg->index; } } *segtail = seg = nasm_malloc(sizeof(*seg)); seg->next = NULL; segtail = &seg->next; seg->index = seg_alloc(); seg->ieee_index = ieee_idx; any_segs = true; seg->name = NULL; seg->currentpos = 0; seg->align = 1; /* default */ seg->use32 = *bits == 32; /* default to user spec */ seg->combine = CMB_PUBLIC; /* default */ seg->pubhead = NULL; seg->pubtail = &seg->pubhead; seg->data = NULL; seg->fptr = NULL; seg->lochead = NULL; seg->loctail = &seg->lochead; /* * Process the segment attributes. */ p = name; while (attrs--) { p += strlen(p); while (!*p) p++; /* * `p' contains a segment attribute. */ if (!nasm_stricmp(p, "private")) seg->combine = CMB_PRIVATE; else if (!nasm_stricmp(p, "public")) seg->combine = CMB_PUBLIC; else if (!nasm_stricmp(p, "common")) seg->combine = CMB_COMMON; else if (!nasm_stricmp(p, "use16")) seg->use32 = false; else if (!nasm_stricmp(p, "use32")) seg->use32 = true; else if (!nasm_strnicmp(p, "align=", 6)) { seg->align = readnum(p + 6, &rn_error); if (seg->align == 0) seg->align = 1; if (rn_error) { seg->align = 1; nasm_error(ERR_NONFATAL, "segment alignment should be" " numeric"); } switch ((int)seg->align) { case 1: /* BYTE */ case 2: /* WORD */ case 4: /* DWORD */ case 16: /* PARA */ case 256: /* PAGE */ case 8: case 32: case 64: case 128: break; default: nasm_error(ERR_NONFATAL, "invalid alignment value %d", seg->align); seg->align = 1; break; } } else if (!nasm_strnicmp(p, "absolute=", 9)) { seg->align = SEG_ABS + readnum(p + 9, &rn_error); if (rn_error) nasm_error(ERR_NONFATAL, "argument to `absolute' segment" " attribute should be numeric"); } } ieee_seg_needs_update = seg; if (seg->align >= SEG_ABS) define_label(name, NO_SEG, seg->align - SEG_ABS, NULL, false, false); else define_label(name, seg->index + 1, 0L, NULL, false, false); ieee_seg_needs_update = NULL; if (seg->use32) *bits = 32; else *bits = 16; return seg->index; } }
static long elf_section_names(char *name, int pass, int *bits) { char *p; int flags_and, flags_or, type, align, i; /* * Default is 32 bits. */ if (!name) { *bits = 32; return def_seg; } p = name; while (*p && !isspace(*p)) p++; if (*p) *p++ = '\0'; flags_and = flags_or = type = align = 0; while (*p && isspace(*p)) p++; while (*p) { char *q = p; while (*p && !isspace(*p)) p++; if (*p) *p++ = '\0'; while (*p && isspace(*p)) p++; if (!nasm_strnicmp(q, "align=", 6)) { align = atoi(q + 6); if (align == 0) align = 1; if ((align - 1) & align) { /* means it's not a power of two */ error(ERR_NONFATAL, "section alignment %d is not" " a power of two", align); align = 1; } } else if (!nasm_stricmp(q, "alloc")) { flags_and |= SHF_ALLOC; flags_or |= SHF_ALLOC; } else if (!nasm_stricmp(q, "noalloc")) { flags_and |= SHF_ALLOC; flags_or &= ~SHF_ALLOC; } else if (!nasm_stricmp(q, "exec")) { flags_and |= SHF_EXECINSTR; flags_or |= SHF_EXECINSTR; } else if (!nasm_stricmp(q, "noexec")) { flags_and |= SHF_EXECINSTR; flags_or &= ~SHF_EXECINSTR; } else if (!nasm_stricmp(q, "write")) { flags_and |= SHF_WRITE; flags_or |= SHF_WRITE; } else if (!nasm_stricmp(q, "nowrite")) { flags_and |= SHF_WRITE; flags_or &= ~SHF_WRITE; } else if (!nasm_stricmp(q, "progbits")) { type = SHT_PROGBITS; } else if (!nasm_stricmp(q, "nobits")) { type = SHT_NOBITS; } } if (!strcmp(name, ".comment") || !strcmp(name, ".shstrtab") || !strcmp(name, ".symtab") || !strcmp(name, ".strtab")) { error(ERR_NONFATAL, "attempt to redefine reserved section" "name `%s'", name); return NO_SEG; } for (i = 0; i < nsects; i++) if (!strcmp(name, sects[i]->name)) break; if (i == nsects) { if (!strcmp(name, ".text")) i = elf_make_section(name, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 16); else if (!strcmp(name, ".rodata")) i = elf_make_section(name, SHT_PROGBITS, SHF_ALLOC, 4); else if (!strcmp(name, ".data")) i = elf_make_section(name, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE, 4); else if (!strcmp(name, ".bss")) i = elf_make_section(name, SHT_NOBITS, SHF_ALLOC | SHF_WRITE, 4); else i = elf_make_section(name, SHT_PROGBITS, SHF_ALLOC, 1); if (type) sects[i]->type = type; if (align) sects[i]->align = align; sects[i]->flags &= ~flags_and; sects[i]->flags |= flags_or; } else if (pass == 1) { if (type || align || flags_and) error(ERR_WARNING, "section attributes ignored on" " redeclaration of section `%s'", name); } return sects[i]->index; }
static long coff_section_names (char *name, int pass, int *bits) { char *p; unsigned long flags, align_and = ~0L, align_or = 0L; int i; /* * Default is 32 bits. */ if (!name) *bits = 32; if (!name) return def_seg; p = name; while (*p && !isspace(*p)) p++; if (*p) *p++ = '\0'; if (strlen(name) > 8) { error (ERR_WARNING, "COFF section names limited to 8 characters:" " truncating"); name[8] = '\0'; } flags = 0; while (*p && isspace(*p)) p++; while (*p) { char *q = p; while (*p && !isspace(*p)) p++; if (*p) *p++ = '\0'; while (*p && isspace(*p)) p++; if (!nasm_stricmp(q, "code") || !nasm_stricmp(q, "text")) { flags = TEXT_FLAGS; } else if (!nasm_stricmp(q, "data")) { flags = DATA_FLAGS; } else if (!nasm_stricmp(q, "bss")) { flags = BSS_FLAGS; } else if (!nasm_stricmp(q, "info")) { if (win32) flags = INFO_FLAGS; else { flags = DATA_FLAGS; /* gotta do something */ error (ERR_NONFATAL, "standard COFF does not support" " informational sections"); } } else if (!nasm_strnicmp(q,"align=",6)) { if (!win32) error (ERR_NONFATAL, "standard COFF does not support" " section alignment specification"); else { if (q[6+strspn(q+6,"0123456789")]) error(ERR_NONFATAL, "argument to `align' is not numeric"); else { unsigned int align = atoi(q+6); if (!align || ((align-1) & align)) error(ERR_NONFATAL, "argument to `align' is not a" " power of two"); else if (align > 64) error(ERR_NONFATAL, "Win32 cannot align sections" " to better than 64-byte boundaries"); else { align_and = ~0x00F00000L; align_or = (align == 1 ? 0x00100000L : align == 2 ? 0x00200000L : align == 4 ? 0x00300000L : align == 8 ? 0x00400000L : align == 16 ? 0x00500000L : align == 32 ? 0x00600000L : 0x00700000L); } } } } } for (i=0; i<nsects; i++) if (!strcmp(name, sects[i]->name)) break; if (i == nsects) { if (!flags) { if (!strcmp(name, ".data")) flags = DATA_FLAGS; else if (!strcmp(name, ".bss")) flags = BSS_FLAGS; else flags = TEXT_FLAGS; } i = coff_make_section (name, flags); if (flags) sects[i]->flags = flags; sects[i]->flags &= align_and; sects[i]->flags |= align_or; } else if (pass == 1) { if (flags) error (ERR_WARNING, "section attributes ignored on" " redeclaration of section `%s'", name); } return sects[i]->index; }