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

📄 outmacho.c

📁 nasm早期的源代码,比较简单是学习汇编和编译原理的好例子
💻 C
📖 第 1 页 / 共 3 页
字号:
    fwriteint32_t(seg_filesize, machofp);      /* in-file size */
    fwriteint32_t(VM_PROT_DEFAULT, machofp);   /* maximum vm protection */
    fwriteint32_t(VM_PROT_DEFAULT, machofp);   /* initial vm protection */
    fwriteint32_t(seg_nsects, machofp);        /* number of sections */
    fwriteint32_t(0, machofp); /* no flags */

    /* emit section headers */
    for (s = sects; s != NULL; s = s->next) {
	fwrite(s->sectname, sizeof(s->sectname), 1, machofp);
	fwrite(s->segname, sizeof(s->segname), 1, machofp);
	fwriteint32_t(s_addr, machofp);
	fwriteint32_t(s->size, machofp);

	/* dummy data for zerofill sections or proper values */
	if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
	    fwriteint32_t(offset, machofp);
	    /* Write out section alignment, as a power of two.
	       e.g. 32-bit word alignment would be 2 (2^^2 = 4).  */
	    fwriteint32_t(s->align, machofp);
	    /* To be compatible with cctools as we emit
	       a zero reloff if we have no relocations.  */
	    fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, machofp);
	    fwriteint32_t(s->nreloc, machofp);

	    offset += s->size;
	    s_reloff += s->nreloc * MACHO_RELINFO_SIZE;
	} else {
	    fwriteint32_t(0, machofp);
	    fwriteint32_t(0, machofp);
	    fwriteint32_t(0, machofp);
	    fwriteint32_t(0, machofp);
	}

	fwriteint32_t(s->flags, machofp);      /* flags */
	fwriteint32_t(0, machofp);     /* reserved */
	fwriteint32_t(0, machofp);     /* reserved */

	s_addr += s->size;
    }

    rel_padcnt = rel_base - offset;
    offset = rel_base + s_reloff;

    return offset;
}

/* For a given chain of relocs r, write out the entire relocation
   chain to the object file.  */

static void macho_write_relocs (struct reloc *r)
{
    while (r) {
	uint32_t word2;

	fwriteint32_t(r->addr, machofp); /* reloc offset */

	word2 = r->snum;
	word2 |= r->pcrel << 24;
	word2 |= r->length << 25;
	word2 |= r->ext << 27;
	word2 |= r->type << 28;
	fwriteint32_t(word2, machofp); /* reloc data */

	r = r->next;
    }
}

/* Write out the section data.  */
static void macho_write_section (void)
{
    struct section *s, *s2;
    struct reloc *r;
    char *rel_paddata = "\0\0\0";
    uint8_t fi, *p, *q, blk[4];
    int32_t l;

    for (s = sects; s != NULL; s = s->next) {
	if ((s->flags & SECTION_TYPE) == S_ZEROFILL)
	    continue;

	/* no padding needs to be done to the sections */

	/* Like a.out Mach-O references things in the data or bss
	 * sections by addresses which are actually relative to the
	 * start of the _text_ section, in the _file_. See outaout.c
	 * for more information. */
	saa_rewind(s->data);
	for (r = s->relocs; r != NULL; r = r->next) {
	    saa_fread(s->data, r->addr, blk, (int32_t)r->length << 1);
	    p = q = blk;
	    l = *p++;

	    /* get offset based on relocation type */
	    if (r->length > 0) {
		l += ((int32_t)*p++) << 8;

		if (r->length == 2) {
		    l += ((int32_t)*p++) << 16;
		    l += ((int32_t)*p++) << 24;
		}
	    }

	    /* If the relocation is internal add to the current section
	       offset. Otherwise the only value we need is the symbol
	       offset which we already have. The linker takes care
	       of the rest of the address.  */
	    if (!r->ext) {
		/* add sizes of previous sections to current offset */
		for (s2 = sects, fi = 1;
		     s2 != NULL && fi < r->snum; s2 = s2->next, fi++)
		    if ((s2->flags & SECTION_TYPE) != S_ZEROFILL)
			l += s2->size;
	    }

	    /* write new offset back */
	    if (r->length == 2)
		WRITELONG(q, l);
	    else if (r->length == 1)
		WRITESHORT(q, l);
	    else
		*q++ = l & 0xFF;

	    saa_fwrite(s->data, r->addr, blk, (int32_t)r->length << 1);
	}

	/* dump the section data to file */
	saa_fpwrite(s->data, machofp);
    }

    /* pad last section up to reloc entries on int32_t boundary */
    fwrite(rel_paddata, rel_padcnt, 1, machofp);

    /* emit relocation entries */
    for (s = sects; s != NULL; s = s->next)
	macho_write_relocs (s->relocs);
}

/* Write out the symbol table. We should already have sorted this
   before now.  */
static void macho_write_symtab (void)
{
    struct symbol *sym;
    struct section *s;
    int32_t fi;
    uint32_t i;

    /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */

    for (sym = syms; sym != NULL; sym = sym->next) {
	if ((sym->type & N_EXT) == 0) {
	    fwriteint32_t(sym->strx, machofp);		/* string table entry number */
	    fwrite(&sym->type, 1, 1, machofp);	/* symbol type */
	    fwrite(&sym->sect, 1, 1, machofp);	/* section */
	    fwriteint16_t(sym->desc, machofp);	/* description */

	    /* Fix up the symbol value now that we know the final section
	       sizes.  */
	    if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
		for (s = sects, fi = 1;
		     s != NULL && fi < sym->sect; s = s->next, ++fi)
		    sym->value += s->size;
	    }

	    fwriteint32_t(sym->value, machofp);	/* value (i.e. offset) */
	}
    }

    for (i = 0; i < nextdefsym; i++) {
	sym = extdefsyms[i];
	fwriteint32_t(sym->strx, machofp);
	fwrite(&sym->type, 1, 1, machofp);	/* symbol type */
	fwrite(&sym->sect, 1, 1, machofp);	/* section */
	fwriteint16_t(sym->desc, machofp);	/* description */

	/* Fix up the symbol value now that we know the final section
	   sizes.  */
	if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
	    for (s = sects, fi = 1;
		 s != NULL && fi < sym->sect; s = s->next, ++fi)
		sym->value += s->size;
	}

	fwriteint32_t(sym->value, machofp);	/* value (i.e. offset) */
    }

     for (i = 0; i < nundefsym; i++) {
	 sym = undefsyms[i];
	 fwriteint32_t(sym->strx, machofp);
	 fwrite(&sym->type, 1, 1, machofp);	/* symbol type */
	 fwrite(&sym->sect, 1, 1, machofp);	/* section */
	 fwriteint16_t(sym->desc, machofp);	/* description */

	 /* Fix up the symbol value now that we know the final section
	    sizes.  */
	 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
	     for (s = sects, fi = 1;
		  s != NULL && fi < sym->sect; s = s->next, ++fi)
		 sym->value += s->size;
	 }

	 fwriteint32_t(sym->value, machofp);	/* value (i.e. offset) */
     }
}

/* Fixup the snum in the relocation entries, we should be
   doing this only for externally undefined symbols. */
static void macho_fixup_relocs (struct reloc *r)
{
    struct symbol *sym;
    uint32_t i;

    while (r != NULL) {
	if (r->ext) {
	    for (i = 0; i < nundefsym; i++) {
		sym = undefsyms[i];
		if (sym->initial_snum == r->snum) {
		    r->snum = sym->snum;
		}
	    }
	}
	r = r->next;
    }
}

/* Write out the object file.  */

static void macho_write (void)
{
    uint32_t offset = 0;

    /* mach-o object file structure:
    **
    ** mach header
    **  uint32_t magic
    **  int   cpu type
    **  int   cpu subtype
    **  uint32_t mach file type
    **  uint32_t number of load commands
    **  uint32_t size of all load commands
    **   (includes section struct size of segment command)
    **  uint32_t flags
    **
    ** segment command
    **  uint32_t command type == LC_SEGMENT
    **  uint32_t size of load command
    **   (including section load commands)
    **  char[16] segment name
    **  uint32_t in-memory offset
    **  uint32_t in-memory size
    **  uint32_t in-file offset to data area
    **  uint32_t in-file size
    **   (in-memory size excluding zerofill sections)
    **  int   maximum vm protection
    **  int   initial vm protection
    **  uint32_t number of sections
    **  uint32_t flags
    **
    ** section commands
    **   char[16] section name
    **   char[16] segment name
    **   uint32_t in-memory offset
    **   uint32_t in-memory size
    **   uint32_t in-file offset
    **   uint32_t alignment
    **    (irrelevant in MH_OBJECT)
    **   uint32_t in-file offset of relocation entires
    **   uint32_t number of relocations
    **   uint32_t flags
    **   uint32_t reserved
    **   uint32_t reserved
    **
    ** symbol table command
    **  uint32_t command type == LC_SYMTAB
    **  uint32_t size of load command
    **  uint32_t symbol table offset
    **  uint32_t number of symbol table entries
    **  uint32_t string table offset
    **  uint32_t string table size
    **
    ** raw section data
    **
    ** padding to int32_t boundary
    **
    ** relocation data (struct reloc)
    ** int32_t offset
    **  uint data (symbolnum, pcrel, length, extern, type)
    **
    ** symbol table data (struct nlist)
    **  int32_t  string table entry number
    **  uint8_t type
    **   (extern, absolute, defined in section)
    **  uint8_t section
    **   (0 for global symbols, section number of definition (>= 1, <=
    **   254) for local symbols, size of variable for common symbols
    **   [type == extern])
    **  int16_t description
    **   (for stab debugging format)
    **  uint32_t value (i.e. file offset) of symbol or stab offset
    **
    ** string table data
    **  list of null-terminated strings
    */

    /* Emit the Mach-O header.  */
    macho_write_header();

    offset = MACHO_HEADER_SIZE + head_sizeofcmds;

    /* emit the segment load command */
    if (seg_nsects > 0)
	offset = macho_write_segment (offset);
    else
        error(ERR_WARNING, "no sections?");

    if (nsyms > 0) {
        /* write out symbol command */
        fwriteint32_t(LC_SYMTAB, machofp); /* cmd == LC_SYMTAB */
        fwriteint32_t(MACHO_SYMCMD_SIZE, machofp); /* size of load command */
        fwriteint32_t(offset, machofp);    /* symbol table offset */
        fwriteint32_t(nsyms, machofp);     /* number of symbol
                                         ** table entries */

        offset += nsyms * MACHO_NLIST_SIZE;
        fwriteint32_t(offset, machofp);    /* string table offset */
        fwriteint32_t(strslen, machofp);   /* string table size */
    }

    /* emit section data */
    if (seg_nsects > 0)
	macho_write_section ();

    /* emit symbol table if we have symbols */
    if (nsyms > 0)
	macho_write_symtab ();

    /* we don't need to pad here since MACHO_NLIST_SIZE == 12 */

    /* emit string table */
    saa_fpwrite(strs, machofp);
}
/* We do quite a bit here, starting with finalizing all of the data
   for the object file, writing, and then freeing all of the data from
   the file.  */

static void macho_cleanup(int debuginfo)
{
    struct section *s;
    struct reloc *r;
    struct symbol *sym;

    (void)debuginfo;

    /* Sort all symbols.  */
    macho_layout_symbols (&nsyms, &strslen);

    /* Fixup relocation entries */
    for (s = sects; s != NULL; s = s->next) {
	macho_fixup_relocs (s->relocs);
    }

    /* First calculate and finalize needed values.  */
    macho_calculate_sizes();
    macho_write();

    /* done - yay! */
    fclose(machofp);

    /* free up everything */
    while (sects->next) {
        s = sects;
        sects = sects->next;

        saa_free(s->data);
        while (s->relocs != NULL) {
            r = s->relocs;
            s->relocs = s->relocs->next;
            nasm_free(r);
        }

        nasm_free(s);
    }

    saa_free(strs);
    raa_free(extsyms);

    if (syms) {
	while (syms->next) {
	    sym = syms;
	    syms = syms->next;

	    nasm_free (sym);
	}
    }
}

/* Debugging routines.  */
static void debug_reloc (struct reloc *r)
{
    fprintf (stdout, "reloc:\n");
    fprintf (stdout, "\taddr: %"PRId32"\n", r->addr);
    fprintf (stdout, "\tsnum: %d\n", r->snum);
    fprintf (stdout, "\tpcrel: %d\n", r->pcrel);
    fprintf (stdout, "\tlength: %d\n", r->length);
    fprintf (stdout, "\text: %d\n", r->ext);
    fprintf (stdout, "\ttype: %d\n", r->type);
}

static void debug_section_relocs (struct section *s)
{
    struct reloc *r = s->relocs;

    fprintf (stdout, "relocs for section %s:\n\n", s->sectname);

    while (r != NULL) {
	debug_reloc (r);
	r = r->next;
    }
}

struct ofmt of_macho = {
    "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X object files",
    "macho",
    NULL,
    null_debug_arr,
    &null_debug_form,
    macho_stdmac,
    macho_init,
    macho_setinfo,
    macho_output,
    macho_symdef,
    macho_section,
    macho_segbase,
    macho_directive,
    macho_filename,
    macho_cleanup
};

#endif

/*
 * Local Variables:
 * mode:c
 * c-basic-offset:4
 * End:
 *
 * end of file */

⌨️ 快捷键说明

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