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

📄 outcoff.c

📁 汇编编译器的最新版本的源码.买了自己动手写操作系统这本书的人一定要下
💻 C
📖 第 1 页 / 共 3 页
字号:
            }
        }
    }

    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, ".rdata"))
                flags = RDATA_FLAGS;
            else if (!strcmp(name, ".bss"))
                flags = BSS_FLAGS;
	    else if (win64 && !strcmp(name, ".pdata"))
		flags = 0x40300040; /* rdata align=4 */
	    else if (win64 && !strcmp(name, ".xdata"))
		flags = 0x40400040; /* rdate align=8 */
            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;
}

static void coff_deflabel(char *name, int32_t segment, int64_t 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] != '@') {
	if (strcmp(name,WRT_IMAGEBASE))
            error(ERR_NONFATAL, "unrecognized special symbol `%s'", name);
        return;
    }

    if (strlen(name) > 8) {
	size_t nlen = strlen(name)+1;
        saa_wbytes(strs, name, nlen);
	strslen += nlen;
    } else
        pos = -1;

    sym = saa_wstruct(syms);

    sym->strpos = pos;
    sym->namlen = strlen(name);
    if (pos == -1)
        strcpy(sym->name, name);
    sym->is_global = !!is_global;
    sym->type = 0;		/* Default to T_NULL (no type) */
    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 int32_t coff_add_reloc(struct Section *sect, int32_t segment,
				int16_t type)
{
    struct Reloc *r;

    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
    sect->tail = &r->next;
    r->next = NULL;

    r->address = sect->len;
    if (segment == NO_SEG)
        r->symbol = 0, r->symbase = ABS_SYMBOL;
    else {
        int i;
        r->symbase = REAL_SYMBOLS;
        for (i = 0; i < nsects; i++)
            if (segment == sects[i]->index) {
                r->symbol = i * 2;
                r->symbase = SECT_SYMBOLS;
                break;
            }
        if (r->symbase == REAL_SYMBOLS)
            r->symbol = raa_read(bsym, segment);
    }
    r->type = type;

    sect->nrelocs++;

    /*
     * Return the fixup for standard COFF common variables.
     */
    if (r->symbase == REAL_SYMBOLS && !(win32 | win64))
        return raa_read(symval, segment);
    else
        return 0;
}

static void coff_out(int32_t segto, const void *data,
		     enum out_type type, uint64_t size,
                     int32_t segment, int32_t wrt)
{
    struct Section *s;
    uint8_t mydata[8], *p;
    int i;

    if (wrt != NO_SEG && !win64) {
        wrt = NO_SEG;           /* continue to do _something_ */
        error(ERR_NONFATAL, "WRT not supported by COFF output formats");
    }

    /*
     * handle absolute-assembly (structure definitions)
     */
    if (segto == NO_SEG) {
        if (type != OUT_RESERVE)
            error(ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
                  " space");
        return;
    }

    s = NULL;
    for (i = 0; i < nsects; i++)
        if (segto == sects[i]->index) {
            s = sects[i];
            break;
        }
    if (!s) {
        int tempint;            /* ignored */
        if (segto != coff_section_names(".text", 2, &tempint))
            error(ERR_PANIC, "strange segment conditions in COFF driver");
        else
            s = sects[nsects - 1];
    }

    /* magically default to 'wrt ..imagebase' in .pdata and .xdata */
    if (win64 && wrt == NO_SEG &&
	(!strcmp(s->name,".pdata") || !strcmp(s->name,".xdata")))
	wrt = imagebase_sect;

    if (!s->data && type != OUT_RESERVE) {
        error(ERR_WARNING, "attempt to initialize memory in"
              " BSS section `%s': ignored", s->name);
        if (type == OUT_REL2ADR)
            size = 2;
        else if (type == OUT_REL4ADR)
            size = 4;
        s->len += size;
        return;
    }

    if (type == OUT_RESERVE) {
        if (s->data) {
            error(ERR_WARNING, "uninitialised space declared in"
                  " non-BSS section `%s': zeroing", s->name);
            coff_sect_write(s, NULL, size);
        } else
            s->len += size;
    } else if (type == OUT_RAWDATA) {
        if (segment != NO_SEG)
            error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
        coff_sect_write(s, data, size);
    } else if (type == OUT_ADDRESS) {
        if (!(win64)) {
            if (size != 4 && (segment != NO_SEG || wrt != NO_SEG))
                error(ERR_NONFATAL, "COFF format does not support non-32-bit"
                      " relocations");
            else {
                int32_t fix = 0;
                if (segment != NO_SEG || wrt != NO_SEG) {
                    if (wrt != NO_SEG) {
                        error(ERR_NONFATAL, "COFF format does not support"
                              " WRT types");
                    } else if (segment % 2) {
                        error(ERR_NONFATAL, "COFF format does not support"
                              " segment base references");
                    } else
                        fix = coff_add_reloc(s, segment, IMAGE_REL_I386_DIR32);
                }
                p = mydata;
                WRITELONG(p, *(int64_t *)data + fix);
                coff_sect_write(s, mydata, size);
            }
        } else {
            int32_t fix = 0;
            p = mydata;
            if (size == 8) {
	        if (wrt == imagebase_sect) {
		    error(ERR_NONFATAL, "operand size mismatch: 'wrt "
			WRT_IMAGEBASE "' is a 32-bit operand");
		}
                fix = coff_add_reloc(s, segment, IMAGE_REL_AMD64_ADDR64);
                WRITEDLONG(p, *(int64_t *)data + fix);
                coff_sect_write(s, mydata, size);
            } else {
                fix = coff_add_reloc(s, segment,
			wrt == imagebase_sect ?	IMAGE_REL_AMD64_ADDR32NB:
						IMAGE_REL_AMD64_ADDR32);
                WRITELONG(p, *(int64_t *)data + fix);
                coff_sect_write(s, mydata, size);
            }
        }
    } else if (type == OUT_REL2ADR) {
        error(ERR_NONFATAL, "COFF format does not support 16-bit"
              " relocations");
    } else if (type == OUT_REL4ADR) {
        if (segment == segto && !(win64))  /* Acceptable for RIP-relative */
            error(ERR_PANIC, "intra-segment OUT_REL4ADR");
        else if (segment == NO_SEG && win32)
            error(ERR_NONFATAL, "Win32 COFF does not correctly support"
                  " relative references to absolute addresses");
        else {
            int32_t fix = 0;
            if (segment != NO_SEG && segment % 2) {
                error(ERR_NONFATAL, "COFF format does not support"
                      " segment base references");
            } else
                fix = coff_add_reloc(s, segment,
			win64 ? IMAGE_REL_AMD64_REL32 : IMAGE_REL_I386_REL32);
            p = mydata;
            if (win32 | win64) {
                WRITELONG(p, *(int64_t *)data + 4 - size + fix);
            } else {
                WRITELONG(p, *(int64_t *)data - (size + s->len) + fix);
            }
            coff_sect_write(s, mydata, 4L);
        }

    }
}

static void coff_sect_write(struct Section *sect,
                            const uint8_t *data, uint32_t len)
{
    saa_wbytes(sect->data, data, len);
    sect->len += len;
}

typedef struct tagString {
    struct tagString *Next;
    int len;
    char *String;
} STRING;

#define EXPORT_SECTION_NAME ".drectve"
#define EXPORT_SECTION_FLAGS INFO_FLAGS
/*
#define EXPORT_SECTION_NAME ".text"
#define EXPORT_SECTION_FLAGS TEXT_FLAGS
*/

static STRING *Exports = NULL;
static struct Section *directive_sec;
void AddExport(char *name)
{
    STRING *rvp = Exports, *newS;

    newS = (STRING *) nasm_malloc(sizeof(STRING));
    newS->len = strlen(name);
    newS->Next = NULL;
    newS->String = (char *)nasm_malloc(newS->len + 1);
    strcpy(newS->String, name);
    if (rvp == NULL) {
        int i;
        for (i = 0; i < nsects; i++)

            if (!strcmp(EXPORT_SECTION_NAME, sects[i]->name))
                break;
        if (i == nsects)
            directive_sec =
                sects[coff_make_section
                      (EXPORT_SECTION_NAME, EXPORT_SECTION_FLAGS)];
        else
            directive_sec = sects[i];
        Exports = newS;
    } else {
        while (rvp->Next) {
            if (!strcmp(rvp->String, name))
                return;
            rvp = rvp->Next;
        }
        rvp->Next = newS;
    }
}

void BuildExportTable(void)
{
    STRING *rvp = Exports, *next;
    uint8_t buf[256];
    int len;
    if (rvp == NULL)
        return;
    while (rvp) {
        len = sprintf((char *)buf, "-export:%s ", rvp->String);
        coff_sect_write(directive_sec, buf, len);
        rvp = rvp->Next;
    }

    next = Exports;
    while ((rvp = next)) {
        next = rvp->Next;
        nasm_free(rvp->String);
        nasm_free(rvp);
    }
    Exports = NULL;
}

static int coff_directives(char *directive, char *value, int pass)
{
    if (!strcmp(directive, "export")) {

⌨️ 快捷键说明

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