📄 outbin.c
字号:
* will always be the first section in the unsorted list). */
for (g = sections, sections = NULL; g; g = gs)
{ /* Find the section that we will insert this group before (s). */
for (sp = §ions, s = sections; s; sp = &s->next, s = s->next)
if ((s->flags & START_DEFINED) && (g->start < s->start)) break;
/* Find the end of the group (gs). */
for (gs = g->next, gsp = &g->next;
gs && !(gs->flags & START_DEFINED);
gsp = &gs->next, gs = gs->next);
/* Re-link the group before the target section. */
*sp = g; *gsp = s;
}
/* Step 3: Compute start addresses for all progbits sections. */
/* Make sure we have an origin and a start address for the first section. */
if (origin_defined)
switch (sections->flags & (START_DEFINED | ALIGN_DEFINED))
{ case START_DEFINED | ALIGN_DEFINED:
case START_DEFINED:
/* Make sure this section doesn't begin before the origin. */
if (sections->start < origin) error(ERR_FATAL, "section %s begins"
" before program origin", sections->name);
break;
case ALIGN_DEFINED:
sections->start = ((origin + sections->align - 1) &
~(sections->align - 1)); break;
case 0:
sections->start = origin;
}
else
{ if (!(sections->flags & START_DEFINED))
sections->start = 0;
origin = sections->start;
}
sections->flags |= START_DEFINED;
/* Make sure each section has an explicit start address. If it
* doesn't, then compute one based its alignment and the end of
* the previous section. */
for (pend = sections->start, g = s = sections; g; g = g->next)
{ /* Find the next section that could cause an overlap situation
* (has a defined start address, and is not zero length). */
if (g == s)
for (s = g->next;
s && ((s->length == 0) || !(s->flags & START_DEFINED));
s = s->next);
/* Compute the start address of this section, if necessary. */
if (!(g->flags & START_DEFINED))
{ /* Default to an alignment of 4 if unspecified. */
if (!(g->flags & ALIGN_DEFINED))
{ g->align = 4; g->flags |= ALIGN_DEFINED;
}
/* Set the section start address. */
g->start = (pend + g->align - 1) & ~(g->align - 1);
g->flags |= START_DEFINED;
}
/* Ugly special case for progbits sections' virtual attributes:
* If there is a defined valign, but no vstart and no vfollows, then
* we valign after the previous progbits section. This case doesn't
* really make much sense for progbits sections with a defined start
* address, but it is possible and we must do *something*.
* Not-so-ugly special case:
* If a progbits section has no virtual attributes, we set the
* vstart equal to the start address. */
if (!(g->flags & (VSTART_DEFINED | VFOLLOWS_DEFINED)))
{ if (g->flags & VALIGN_DEFINED)
g->vstart = (pend + g->valign - 1) & ~(g->valign - 1);
else g->vstart = g->start;
g->flags |= VSTART_DEFINED;
}
/* Ignore zero-length sections. */
if (g->start < pend) continue;
/* Compute the span of this section. */
pend = g->start + g->length;
/* Check for section overlap. */
if (s)
{ if (g->start > s->start)
error(ERR_FATAL, "sections %s ~ %s and %s overlap!",
gs->name, g->name, s->name);
if (pend > s->start)
error(ERR_FATAL, "sections %s and %s overlap!",
g->name, s->name);
}
/* Remember this section as the latest >0 length section. */
gs = g;
}
/* Step 4: Compute vstart addresses for all sections. */
/* Attach the nobits sections to the end of the progbits sections. */
for (s = sections; s->next; s = s->next); s->next = nobits;
last_progbits = s;
/* Scan for sections that don't have a vstart address. If we find one we'll
* attempt to compute its vstart. If we can't compute the vstart, we leave
* it alone and come back to it in a subsequent scan. We continue scanning
* and re-scanning until we've gone one full cycle without computing any
* vstarts. */
do
{ /* Do one full scan of the sections list. */
for (h = 0, g = sections; g; g = g->next)
{ if (g->flags & VSTART_DEFINED) continue;
/* Find the section that this one virtually follows. */
if (g->flags & VFOLLOWS_DEFINED)
{ for (s = sections; s && strcmp(g->vfollows, s->name); s = s->next);
if (!s) error(ERR_FATAL, "section %s vfollows unknown section (%s)",
g->name, g->vfollows);
}
else if (g->ifollows != NULL)
for (s = sections; s && (s != g->ifollows); s = s->next);
/* The .bss section is the only one with ifollows = NULL. In this case we
* implicitly follow the last progbits section. */
else s = last_progbits;
/* If the section we're following has a vstart, we can proceed. */
if (s->flags & VSTART_DEFINED)
{ /* Default to virtual alignment of four. */
if (!(g->flags & VALIGN_DEFINED))
{ g->valign = 4; g->flags |= VALIGN_DEFINED;
}
/* Compute the vstart address. */
g->vstart = (s->vstart + s->length + g->valign - 1) & ~(g->valign - 1);
g->flags |= VSTART_DEFINED; h++;
/* Start and vstart mean the same thing for nobits sections. */
if (g->flags & TYPE_NOBITS) g->start = g->vstart;
}
}
} while (h);
/* Now check for any circular vfollows references, which will manifest
* themselves as sections without a defined vstart. */
for (h = 0, s = sections; s; s = s->next)
{ if (!(s->flags & VSTART_DEFINED))
{ /* Non-fatal errors after assembly has completed are generally a
* no-no, but we'll throw a fatal one eventually so it's ok. */
error(ERR_NONFATAL, "cannot compute vstart for section %s", s->name);
h++;
}
}
if (h) error(ERR_FATAL, "circular vfollows path detected");
#ifdef DEBUG
fprintf(stdout, "bin_cleanup: Confirm final section order for output file:\n");
for (h = 0, s = sections; s && (s->flags & TYPE_PROGBITS); h++, s = s->next)
fprintf(stdout, "%i. %s\n", h, s->name);
#endif
/* Step 5: Apply relocations. */
/* Prepare the sections for relocating. */
for (s = sections; s; s = s->next) saa_rewind(s->contents);
/* Apply relocations. */
for (r = relocs; r; r = r->next)
{ unsigned char *p, *q, mydata[4];
long l;
saa_fread (r->target->contents, r->posn, mydata, r->bytes);
p = q = mydata;
l = *p++;
if (r->bytes > 1)
{ l += ((long)*p++) << 8;
if (r->bytes == 4)
{ l += ((long)*p++) << 16;
l += ((long)*p++) << 24;
}
}
s = find_section_by_index(r->secref);
if (s)
{ if (r->secref == s->start_index) l += s->start;
else l += s->vstart;
}
s = find_section_by_index(r->secrel);
if (s)
{ if (r->secrel == s->start_index) l -= s->start;
else l -= s->vstart;
}
if (r->bytes == 4) WRITELONG(q, l);
else if (r->bytes == 2) WRITESHORT(q, l);
else *q++ = (unsigned char) (l & 0xFF);
saa_fwrite(r->target->contents, r->posn, mydata, r->bytes);
}
/* Step 6: Write the section data to the output file. */
/* Write the progbits sections to the output file. */
for(pend = origin, s = sections; s && (s->flags & TYPE_PROGBITS); s = s->next)
{ /* Skip zero-length sections. */
if (s->length == 0) continue;
/* Pad the space between sections. */
for (h = s->start - pend; h; h--)
fputc('\0', fp);
/* Write the section to the output file. */
if (s->length > 0) saa_fpwrite(s->contents, fp);
pend = s->start + s->length;
}
/* Done writing the file, so close it. */
fclose(fp);
/* Step 7: Generate the map file. */
if (map_control)
{ const char *not_defined = { "not defined" };
/* Display input and output file names. */
fprintf(rf, "\n- NASM Map file ");
for (h = 63; h; h--) fputc('-', rf);
fprintf(rf, "\n\nSource file: %s\nOutput file: %s\n\n",
infile, outfile);
if (map_control & MAP_ORIGIN)
{ /* Display program origin. */
fprintf(rf, "-- Program origin ");
for (h = 61; h; h--) fputc('-', rf);
fprintf(rf, "\n\n%08lX\n\n", origin);
}
/* Display sections summary. */
if (map_control & MAP_SUMMARY)
{ fprintf(rf, "-- Sections (summary) ");
for (h = 57; h; h--) fputc('-', rf);
fprintf(rf, "\n\nVstart Start Stop "
"Length Class Name\n");
for (s = sections; s; s = s->next)
{ fprintf(rf, "%08lX %08lX %08lX %08lX ",
s->vstart, s->start, s->start + s->length, s->length);
if (s->flags & TYPE_PROGBITS) fprintf(rf, "progbits ");
else fprintf(rf, "nobits ");
fprintf(rf, "%s\n", s->name);
}
fprintf(rf, "\n");
}
/* Display detailed section information. */
if (map_control & MAP_SECTIONS)
{ fprintf(rf, "-- Sections (detailed) ");
for (h = 56; h; h--) fputc('-', rf);
fprintf(rf, "\n\n");
for (s = sections; s; s = s->next)
{ fprintf(rf, "---- Section %s ", s->name);
for (h = 65 - strlen(s->name); h; h--) fputc('-', rf);
fprintf(rf, "\n\nclass: ");
if (s->flags & TYPE_PROGBITS) fprintf(rf, "progbits");
else fprintf(rf, "nobits");
fprintf(rf, "\nlength: %08lX\nstart: %08lX"
"\nalign: ", s->length, s->start);
if (s->flags & ALIGN_DEFINED) fprintf(rf, "%08lX", s->align);
else fprintf(rf, not_defined);
fprintf(rf, "\nfollows: ");
if (s->flags & FOLLOWS_DEFINED) fprintf(rf, "%s", s->follows);
else fprintf(rf, not_defined);
fprintf(rf, "\nvstart: %08lX\nvalign: ", s->vstart);
if (s->flags & VALIGN_DEFINED) fprintf(rf, "%08lX", s->valign);
else fprintf(rf, not_defined);
fprintf(rf, "\nvfollows: ");
if (s->flags & VFOLLOWS_DEFINED) fprintf(rf, "%s", s->vfollows);
else fprintf(rf, not_defined);
fprintf(rf, "\n\n");
}
}
/* Display symbols information. */
if (map_control & MAP_SYMBOLS)
{ long segment, offset;
fprintf(rf, "-- Symbols ");
for (h = 68; h; h--) fputc('-', rf);
fprintf(rf, "\n\n");
if (no_seg_labels)
{ fprintf(rf, "---- No Section ");
for (h = 63; h; h--) fputc('-', rf);
fprintf(rf, "\n\nValue Name\n");
for (l = no_seg_labels; l; l = l->next)
{ lookup_label(l->name, &segment, &offset);
fprintf(rf, "%08lX %s\n", offset, l->name);
}
fprintf(rf, "\n\n");
}
for (s = sections; s; s = s->next)
{ if (s->labels)
{ fprintf(rf, "---- Section %s ", s->name);
for (h = 65 - strlen(s->name); h; h--) fputc('-', rf);
fprintf(rf, "\n\nReal Virtual Name\n");
for (l = s->labels; l; l = l->next)
{ lookup_label(l->name, &segment, &offset);
fprintf(rf, "%08lX %08lX %s\n", s->start + offset,
s->vstart + offset, l->name);
}
fprintf(rf, "\n");
}
}
}
}
/* Close the report file. */
if (map_control && (rf != stdout) && (rf != stderr))
fclose(rf);
/* Step 8: Release all allocated memory. */
/* Free sections, label pointer structs, etc.. */
while (sections)
{ s = sections; sections = s->next;
saa_free(s->contents);
nasm_free(s->name);
if (s->flags & FOLLOWS_DEFINED) nasm_free(s->follows);
if (s->flags & VFOLLOWS_DEFINED) nasm_free(s->vfollows);
while (s->labels)
{ l = s->labels; s->labels = l->next;
nasm_free(l);
}
nasm_free(s);
}
/* Free no-section labels. */
while (no_seg_labels)
{ l = no_seg_labels; no_seg_labels = l->next;
nasm_free(l);
}
/* Free relocation structures. */
while (relocs)
{ r = relocs->next;
nasm_free(relocs);
relocs = r;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -