📄 outmacho.c
字号:
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(§ionAttributes, " \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(§ionAttributes, " \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 + -