⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 outmacho.c

📁 nasm早期的源代码,比较简单是学习汇编和编译原理的好例子
💻 C
📖 第 1 页 / 共 3 页
字号:
    case OUT_RESERVE:
        if (s != sbss) {
            error(ERR_WARNING, "uninitialized space declared in"
                  " %s section: zeroing",
                  get_section_name_by_index(secto));

            sect_write(s, NULL, realbytes);
        } else
            s->size += realbytes;

        break;

    case OUT_RAWDATA:
        if (section != NO_SEG)
            error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");

        sect_write(s, data, realbytes);
        break;

    case OUT_ADDRESS:
        addr = *(int32_t *)data;

        if (section != NO_SEG) {
            if (section % 2) {
                error(ERR_NONFATAL, "Mach-O format does not support"
                      " section base references");
            } else
                add_reloc(s, section, 0, realbytes);
        }

        p = mydata;

        if (realbytes == 2)
            WRITESHORT(p, addr);
        else
            WRITELONG(p, addr);

        sect_write(s, mydata, realbytes);
        break;

    case OUT_REL2ADR:
        if (section == secto)
            error(ERR_PANIC, "intra-section OUT_REL2ADR");

        if (section != NO_SEG && section % 2) {
            error(ERR_NONFATAL, "Mach-O format does not support"
                  " section base references");
        } else
            add_reloc(s, section, 1, 2);

        p = mydata;
        WRITESHORT(p, *(int32_t *)data - (realbytes + s->size));
        sect_write(s, mydata, 2L);
        break;

    case OUT_REL4ADR:
        if (section == secto)
            error(ERR_PANIC, "intra-section OUT_REL4ADR");

        if (section != NO_SEG && section % 2) {
            error(ERR_NONFATAL, "Mach-O format does not support"
                  " section base references");
        } else
            add_reloc(s, section, 1, 4);

        p = mydata;
        WRITELONG(p, *(int32_t *)data - (realbytes + s->size));
        sect_write(s, mydata, 4L);
        break;

    default:
        error(ERR_PANIC, "unknown output type?");
        break;
    }
}

static int32_t macho_section(char *name, int pass, int *bits)
{
    int32_t index, originalIndex;
    char *sectionAttributes;
    struct sectmap *sm;
    struct section *s;

    (void)pass;

    /* Default to 32 bits. */
    if (!name) {
        *bits = 32;
        name = ".text";
        sectionAttributes = NULL;
    } else {
        sectionAttributes = name;
        name = nasm_strsep(&sectionAttributes, " \t");
    }

    for (sm = sectmap; sm->nasmsect != NULL; ++sm) {
        /* make lookup into section name translation table */
        if (!strcmp(name, sm->nasmsect)) {
            char *currentAttribute;

            /* try to find section with that name */
            originalIndex = index = get_section_index_by_name(sm->segname,
                                                              sm->sectname);

            /* create it if it doesn't exist yet */
            if (index == -1) {
                s = *sectstail = nasm_malloc(sizeof(struct section));
                s->next = NULL;
                sectstail = &s->next;

                s->data = saa_init(1L);
                s->index = seg_alloc();
                s->relocs = NULL;
                s->align = DEFAULT_SECTION_ALIGNMENT;

                xstrncpy(s->segname, sm->segname);
                xstrncpy(s->sectname, sm->sectname);
                s->size = 0;
                s->nreloc = 0;
                s->flags = sm->flags;

                index = s->index;
            } else {
                s = get_section_by_index(index);
            }

            while ((NULL != sectionAttributes)
                   && (currentAttribute = nasm_strsep(&sectionAttributes, " \t"))) {
                if (0 != *currentAttribute) {
                    if (!nasm_strnicmp("align=", currentAttribute, 6)) {
                        char *end;
                        int newAlignment, value;

                        value = strtoul(currentAttribute + 6, (char**)&end, 0);
                        newAlignment = exact_log2(value);

                        if (0 != *end) {
                            error(ERR_PANIC,
                                  "unknown or missing alignment value \"%s\" "
                                      "specified for section \"%s\"",
                                  currentAttribute + 6,
                                  name);
                            return NO_SEG;
                        } else if (0 > newAlignment) {
                            error(ERR_PANIC,
                                  "alignment of %d (for section \"%s\") is not "
                                      "a power of two",
                                  value,
                                  name);
                            return NO_SEG;
                        }

                        if ((-1 != originalIndex)
                            && (s->align != newAlignment)) {
                            error(ERR_PANIC,
                                  "section \"%s\" has already been specified "
                                      "with alignment %d, conflicts with new "
                                      "alignment of %d",
                            name,
                            (1 << s->align),
                            value);
                            return NO_SEG;
                        }

                        s->align = newAlignment;
                    } else if (!nasm_stricmp("data", currentAttribute)) {
                        /* Do nothing; 'data' is implicit */
                    } else {
                        error(ERR_PANIC,
                              "unknown section attribute %s for section %s",
                              currentAttribute,
                              name);
                        return NO_SEG;
                    }
                }
            }

            return index;
        }
    }

    error(ERR_PANIC, "invalid section name %s", name);
    return NO_SEG;
}

static void macho_symdef(char *name, int32_t section, int32_t offset,
                         int is_global, char *special)
{
    struct symbol *sym;

    if (special) {
        error(ERR_NONFATAL, "The Mach-O output format does "
              "not support any special symbol types");
        return;
    }

    if (is_global == 3) {
        error(ERR_NONFATAL, "The Mach-O format does not "
              "(yet) support forward reference fixups.");
        return;
    }

    sym = *symstail = nasm_malloc(sizeof(struct symbol));
    sym->next = NULL;
    symstail = &sym->next;

    sym->name = name;
    sym->strx = strslen;
    sym->type = 0;
    sym->desc = 0;
    sym->value = offset;
    sym->initial_snum = -1;

    /* external and common symbols get N_EXT */
    if (is_global != 0)
        sym->type |= N_EXT;

    if (section == NO_SEG) {
        /* symbols in no section get absolute */
        sym->type |= N_ABS;
        sym->sect = NO_SECT;
    } else {
        sym->type |= N_SECT;

        /* get the in-file index of the section the symbol was defined in */
        sym->sect = get_section_fileindex_by_index(section);

        if (sym->sect == NO_SECT) {
            /* remember symbol number of references to external
             ** symbols, this works because every external symbol gets
             ** its own section number allocated internally by nasm and
             ** can so be used as a key */
	    extsyms = raa_write(extsyms, section, nsyms);
	    sym->initial_snum = nsyms;

            switch (is_global) {
            case 1:
            case 2:
                /* there isn't actually a difference between global
                 ** and common symbols, both even have their size in
                 ** sym->value */
                sym->type = N_EXT;
                break;

            default:
                /* give an error on unfound section if it's not an
                 ** external or common symbol (assemble_file() does a
                 ** seg_alloc() on every call for them) */
                error(ERR_PANIC, "in-file index for section %d not found",
                      section);
            }
        }
    }

    ++nsyms;
}

static int32_t macho_segbase(int32_t section)
{
    return section;
}

static int macho_directive(char *directive, char *value, int pass)
{
    (void)directive;
    (void)value;
    (void)pass;
    return 0;
}

static void macho_filename(char *inname, char *outname, efunc error)
{
    standard_extension(inname, outname, ".o", error);
}

static const char *macho_stdmac[] = {
    "%define __SECT__ [section .text]",
    "%macro __NASM_CDecl__ 1",
    "%endmacro",
    NULL
};

/* Comparison function for qsort symbol layout.  */
static int layout_compare (const struct symbol **s1,
			   const struct symbol **s2)
{
    return (strcmp ((*s1)->name, (*s2)->name));
}

/* The native assembler does a few things in a similar function

	* Remove temporary labels
	* Sort symbols according to local, external, undefined (by name)
	* Order the string table

   We do not remove temporary labels right now.

   numsyms is the total number of symbols we have. strtabsize is the
   number entries in the string table.  */

static void macho_layout_symbols (uint32_t *numsyms,
				  uint32_t *strtabsize)
{
    struct symbol *sym, **symp;
    uint32_t i,j;

    *numsyms = 0;
    *strtabsize = sizeof (char);

    symp = &syms;

    while ((sym = *symp)) {
	/* Undefined symbols are now external.  */
	if (sym->type == N_UNDF)
	    sym->type |= N_EXT;

	if ((sym->type & N_EXT) == 0) {
	    sym->snum = *numsyms;
	    *numsyms = *numsyms + 1;
	    nlocalsym++;
	}
	else {
	    if ((sym->type & N_TYPE) != N_UNDF)
		nextdefsym++;
	    else
		nundefsym++;

	    /* If we handle debug info we'll want
	       to check for it here instead of just
	       adding the symbol to the string table.  */
	    sym->strx = *strtabsize;
	    saa_wbytes (strs, sym->name, (int32_t)(strlen(sym->name) + 1));
	    *strtabsize += strlen(sym->name) + 1;
	}
	symp = &(sym->next);
    }

    /* Next, sort the symbols.  Most of this code is a direct translation from
       the Apple cctools symbol layout. We need to keep compatibility with that.  */
    /* Set the indexes for symbol groups into the symbol table */
    ilocalsym = 0;
    iextdefsym = nlocalsym;
    iundefsym = nlocalsym + nextdefsym;

    /* allocate arrays for sorting externals by name */
    extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *));
    undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *));

    i = 0;
    j = 0;

    symp = &syms;

    while ((sym = *symp)) {

	if((sym->type & N_EXT) == 0) {
	    sym->strx = *strtabsize;
	    saa_wbytes (strs, sym->name, (int32_t)(strlen (sym->name) + 1));
	    *strtabsize += strlen(sym->name) + 1;
	}
	else {
	    if((sym->type & N_TYPE) != N_UNDF)
		extdefsyms[i++] = sym;
	    else
		undefsyms[j++] = sym;
	}
	symp = &(sym->next);
    }

    qsort(extdefsyms, nextdefsym, sizeof(struct symbol *),
	  (int (*)(const void *, const void *))layout_compare);
    qsort(undefsyms, nundefsym, sizeof(struct symbol *),
	  (int (*)(const void *, const void *))layout_compare);

    for(i = 0; i < nextdefsym; i++) {
	extdefsyms[i]->snum = *numsyms;
	*numsyms += 1;
    }
    for(j = 0; j < nundefsym; j++) {
	undefsyms[j]->snum = *numsyms;
	*numsyms += 1;
    }
}

/* Calculate some values we'll need for writing later.  */

static void macho_calculate_sizes (void)
{
    struct section *s;

    /* count sections and calculate in-memory and in-file offsets */
    for (s = sects; s != NULL; s = s->next) {
        /* zerofill sections aren't actually written to the file */
        if ((s->flags & SECTION_TYPE) != S_ZEROFILL)
            seg_filesize += s->size;

        seg_vmsize += s->size;
        ++seg_nsects;
    }

    /* calculate size of all headers, load commands and sections to
    ** get a pointer to the start of all the raw data */
    if (seg_nsects > 0) {
        ++head_ncmds;
        head_sizeofcmds +=
            MACHO_SEGCMD_SIZE + seg_nsects * MACHO_SECTCMD_SIZE;
    }

    if (nsyms > 0) {
	++head_ncmds;
	head_sizeofcmds += MACHO_SYMCMD_SIZE;
    }
}

/* Write out the header information for the file.  */

static void macho_write_header (void)
{
    fwriteint32_t(MH_MAGIC, machofp);	/* magic */
    fwriteint32_t(CPU_TYPE_I386, machofp);	/* CPU type */
    fwriteint32_t(CPU_SUBTYPE_I386_ALL, machofp);	/* CPU subtype */
    fwriteint32_t(MH_OBJECT, machofp);	/* Mach-O file type */
    fwriteint32_t(head_ncmds, machofp);	/* number of load commands */
    fwriteint32_t(head_sizeofcmds, machofp);	/* size of load commands */
    fwriteint32_t(0, machofp);	/* no flags */
}

/* Write out the segment load command at offset.  */

static uint32_t macho_write_segment (uint32_t offset)
{
    uint32_t s_addr = 0;
    uint32_t rel_base = alignint32_t (offset + seg_filesize);
    uint32_t s_reloff = 0;
    struct section *s;

    fwriteint32_t(LC_SEGMENT, machofp);        /* cmd == LC_SEGMENT */

    /* size of load command including section load commands */
    fwriteint32_t(MACHO_SEGCMD_SIZE + seg_nsects *
	       MACHO_SECTCMD_SIZE, machofp);

    /* in an MH_OBJECT file all sections are in one unnamed (name
    ** all zeros) segment */
    fwrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 1, machofp);
    fwriteint32_t(0, machofp); /* in-memory offset */
    fwriteint32_t(seg_vmsize, machofp);        /* in-memory size */
    fwriteint32_t(offset, machofp);    /* in-file offset to data */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -