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

📄 outelf.c

📁 一个汇编语言编译器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		} else {
		    error (ERR_NONFATAL, "ELF format does not support this"
			   " use of WRT");
		    wrt = NO_SEG;      /* we can at least _try_ to continue */
		}
	    }
	}
	p = mydata;
	if (realbytes != 4 && segment != NO_SEG)
	    error (ERR_NONFATAL, "ELF format does not support non-32-bit"
		   " relocations");
	WRITELONG (p, addr);
	elf_sect_write (s, mydata, realbytes);
    } else if (type == OUT_REL2ADR) {
	error (ERR_NONFATAL, "ELF format does not support 16-bit"
	       " relocations");
    } else if (type == OUT_REL4ADR) {
	if (segment == segto)
	    error(ERR_PANIC, "intra-segment OUT_REL4ADR");
	if (segment != NO_SEG && segment % 2) {
	    error(ERR_NONFATAL, "ELF format does not support"
		  " segment base references");
	} else {
	    if (wrt == NO_SEG) {
		elf_add_reloc (s, segment, R_386_PC32);
	    } else if (wrt == elf_plt_sect+1) {
		elf_add_reloc (s, segment, R_386_PLT32);
	    } else if (wrt == elf_gotpc_sect+1 ||
		       wrt == elf_gotoff_sect+1 ||
		       wrt == elf_got_sect+1) {
		error(ERR_NONFATAL, "ELF format cannot produce PC-"
		      "relative GOT references");
	    } else {
		error (ERR_NONFATAL, "ELF format does not support this"
		       " use of WRT");
		wrt = NO_SEG;      /* we can at least _try_ to continue */
	    }
	}
	p = mydata;
	WRITELONG (p, *(long*)data - realbytes);
	elf_sect_write (s, mydata, 4L);
    }
}

static void elf_write(void) 
{
    int nsections, align;
    char *p;
    int commlen;
    char comment[64];
    int i;

    struct SAA *symtab;
    long symtablen, symtablocal;

    /*
     * Work out how many sections we will have. We have SHN_UNDEF,
     * then the flexible user sections, then the four fixed
     * sections `.comment', `.shstrtab', `.symtab' and `.strtab',
     * then optionally relocation sections for the user sections.
     */
    nsections = 5;		       /* SHN_UNDEF and the fixed ones */
    add_sectname ("", ".comment");
    add_sectname ("", ".shstrtab");
    add_sectname ("", ".symtab");
    add_sectname ("", ".strtab");
    for (i=0; i<nsects; i++) {
	nsections++;		       /* for the section itself */
	if (sects[i]->head) {
	    nsections++;	       /* for its relocations */
	    add_sectname (".rel", sects[i]->name);
	}
    }

    /*
     * Do the comment.
     */
    *comment = '\0';
    commlen = 2+sprintf(comment+1, "The Netwide Assembler %s", NASM_VER);

    /*
     * Output the ELF header.
     */
    fwrite ("\177ELF\1\1\1\0\0\0\0\0\0\0\0\0", 16, 1, elffp);
    fwriteshort (1, elffp);	       /* ET_REL relocatable file */
    fwriteshort (3, elffp);	       /* EM_386 processor ID */
    fwritelong (1L, elffp);	       /* EV_CURRENT file format version */
    fwritelong (0L, elffp);	       /* no entry point */
    fwritelong (0L, elffp);	       /* no program header table */
    fwritelong (0x40L, elffp);	       /* section headers straight after
					* ELF header plus alignment */
    fwritelong (0L, elffp);	       /* 386 defines no special flags */
    fwriteshort (0x34, elffp);	       /* size of ELF header */
    fwriteshort (0, elffp);	       /* no program header table, again */
    fwriteshort (0, elffp);	       /* still no program header table */
    fwriteshort (0x28, elffp);	       /* size of section header */
    fwriteshort (nsections, elffp);    /* number of sections */
    fwriteshort (nsects+2, elffp);     /* string table section index for
					* section header table */
    fwritelong (0L, elffp);	       /* align to 0x40 bytes */
    fwritelong (0L, elffp);
    fwritelong (0L, elffp);

    /*
     * Build the symbol table and relocation tables.
     */
    symtab = elf_build_symtab (&symtablen, &symtablocal);
    for (i=0; i<nsects; i++)
	if (sects[i]->head)
	    sects[i]->rel = elf_build_reltab (&sects[i]->rellen,
					      sects[i]->head);

    /*
     * Now output the section header table.
     */

    elf_foffs = 0x40 + 0x28 * nsections;
    align = ((elf_foffs+SEG_ALIGN_1) & ~SEG_ALIGN_1) - elf_foffs;
    elf_foffs += align;
    elf_nsect = 0;
    elf_sects = nasm_malloc(sizeof(*elf_sects) * (2 * nsects + 10));

    elf_section_header (0, 0, 0, NULL, FALSE, 0L, 0, 0, 0, 0); /* SHN_UNDEF */
    p = shstrtab+1;
    for (i=0; i<nsects; i++) {
	elf_section_header (p - shstrtab, sects[i]->type, sects[i]->flags,
			    (sects[i]->type == SHT_PROGBITS ?
			     sects[i]->data : NULL), TRUE,
			    sects[i]->len, 0, 0, sects[i]->align, 0);
	p += strlen(p)+1;
    }
    elf_section_header (p - shstrtab, 1, 0, comment, FALSE,
			(long)commlen, 0, 0, 1, 0);/* .comment */
    p += strlen(p)+1;
    elf_section_header (p - shstrtab, 3, 0, shstrtab, FALSE,
			(long)shstrtablen, 0, 0, 1, 0);/* .shstrtab */
    p += strlen(p)+1;
    elf_section_header (p - shstrtab, 2, 0, symtab, TRUE,
			symtablen, nsects+4, symtablocal, 4, 16);/* .symtab */
    p += strlen(p)+1;
    elf_section_header (p - shstrtab, 3, 0, strs, TRUE,
			strslen, 0, 0, 1, 0);	    /* .strtab */
    for (i=0; i<nsects; i++) if (sects[i]->head) {
	p += strlen(p)+1;
	elf_section_header (p - shstrtab, 9, 0, sects[i]->rel, TRUE,
			    sects[i]->rellen, nsects+3, i+1, 4, 8);
    }

    fwrite (align_str, align, 1, elffp);

    /*
     * Now output the sections.
     */
    elf_write_sections();

    nasm_free (elf_sects);
    saa_free (symtab);
}

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 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;
}

static void elf_section_header (int name, int type, int flags,
				void *data, int is_saa, long datalen,
				int link, int info, int align, int eltsize) 
{
    elf_sects[elf_nsect].data = data;
    elf_sects[elf_nsect].len = datalen;
    elf_sects[elf_nsect].is_saa = is_saa;
    elf_nsect++;

    fwritelong ((long)name, elffp);
    fwritelong ((long)type, elffp);
    fwritelong ((long)flags, elffp);
    fwritelong (0L, elffp);	       /* no address, ever, in object files */
    fwritelong (type == 0 ? 0L : elf_foffs, elffp);
    fwritelong (datalen, elffp);
    if (data)
	elf_foffs += (datalen+SEG_ALIGN_1) & ~SEG_ALIGN_1;
    fwritelong ((long)link, elffp);
    fwritelong ((long)info, elffp);
    fwritelong ((long)align, elffp);
    fwritelong ((long)eltsize, elffp);
}

static void elf_write_sections (void) 
{
    int i;
    for (i = 0; i < elf_nsect; i++)
	if (elf_sects[i].data) {
	    long len = elf_sects[i].len;
	    long reallen = (len+SEG_ALIGN_1) & ~SEG_ALIGN_1;
	    long align = reallen - len;
	    if (elf_sects[i].is_saa)
		saa_fpwrite (elf_sects[i].data, elffp);
	    else
		fwrite (elf_sects[i].data, len, 1, elffp);
	    fwrite (align_str, align, 1, elffp);
	}
}

static void elf_sect_write (struct Section *sect,
			     unsigned char *data, unsigned long len) 
{
    saa_wbytes (sect->data, data, len);
    sect->len += len;
}

static long elf_segbase (long segment) 
{
    return segment;
}

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

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

static char *elf_stdmac[] = {
    "%define __SECT__ [section .text]",
    "%macro __NASM_CDecl__ 1",
    "%define $_%1 $%1",
    "%endmacro",
    NULL
};
static int elf_set_info(enum geninfo type, char **val)
{
    return 0;
}

struct ofmt of_elf = {
    "ELF32 (i386) object files (e.g. Linux)",
    "elf",
    NULL,
    null_debug_arr,
    &null_debug_form,
    elf_stdmac,
    elf_init,
    elf_set_info,
    elf_out,
    elf_deflabel,
    elf_section_names,
    elf_segbase,
    elf_directive,
    elf_filename,
    elf_cleanup
};

#endif /* OF_ELF */

⌨️ 快捷键说明

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