📄 outcoff.c
字号:
}
}
}
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 + -