📄 outbin.c
字号:
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -