📄 outobj.c
字号:
}
if (eb)
method |= 0x20, fidx = eb->exts[i]->index;
else
error(ERR_PANIC,
"unrecognised WRT value in obj_write_fixup");
}
}
}
forp = obj_byte(forp, method);
if (fidx != -1)
forp = obj_index(forp, fidx);
forp = obj_index(forp, tidx);
obj_commit(forp);
}
static long obj_segment(char *name, int pass, int *bits)
{
/*
* We call the label manager here to define a name for the new
* segment, and when our _own_ label-definition stub gets
* called in return, it should register the new segment name
* using the pointer it gets passed. That way we save memory,
* by sponging off the label manager.
*/
#if defined(DEBUG) && DEBUG>=3
fprintf(stderr, " obj_segment: < %s >, pass=%d, *bits=%d\n",
name, pass, *bits);
#endif
if (!name) {
*bits = 16;
current_seg = NULL;
return first_seg;
} else {
struct Segment *seg;
struct Group *grp;
struct External **extp;
int obj_idx, i, attrs, rn_error;
char *p;
/*
* Look for segment attributes.
*/
attrs = 0;
while (*name == '.')
name++; /* hack, but a documented one */
p = name;
while (*p && !isspace(*p))
p++;
if (*p) {
*p++ = '\0';
while (*p && isspace(*p))
*p++ = '\0';
}
while (*p) {
while (*p && !isspace(*p))
p++;
if (*p) {
*p++ = '\0';
while (*p && isspace(*p))
*p++ = '\0';
}
attrs++;
}
obj_idx = 1;
for (seg = seghead; seg; seg = seg->next) {
obj_idx++;
if (!strcmp(seg->name, name)) {
if (attrs > 0 && pass == 1)
error(ERR_WARNING, "segment attributes specified on"
" redeclaration of segment: ignoring");
if (seg->use32)
*bits = 32;
else
*bits = 16;
current_seg = seg;
return seg->index;
}
}
*segtail = seg = nasm_malloc(sizeof(*seg));
seg->next = NULL;
segtail = &seg->next;
seg->index = (any_segs ? seg_alloc() : first_seg);
seg->obj_index = obj_idx;
seg->grp = NULL;
any_segs = TRUE;
seg->name = NULL;
seg->currentpos = 0;
seg->align = 1; /* default */
seg->use32 = FALSE; /* default */
seg->combine = CMB_PUBLIC; /* default */
seg->segclass = seg->overlay = NULL;
seg->pubhead = NULL;
seg->pubtail = &seg->pubhead;
seg->lochead = NULL;
seg->loctail = &seg->lochead;
seg->orp = obj_new();
seg->orp->up = &(seg->orp);
seg->orp->ori = ori_ledata;
seg->orp->type = LEDATA;
seg->orp->parm[1] = obj_idx;
/*
* Process the segment attributes.
*/
p = name;
while (attrs--) {
p += strlen(p);
while (!*p)
p++;
/*
* `p' contains a segment attribute.
*/
if (!nasm_stricmp(p, "private"))
seg->combine = CMB_PRIVATE;
else if (!nasm_stricmp(p, "public"))
seg->combine = CMB_PUBLIC;
else if (!nasm_stricmp(p, "common"))
seg->combine = CMB_COMMON;
else if (!nasm_stricmp(p, "stack"))
seg->combine = CMB_STACK;
else if (!nasm_stricmp(p, "use16"))
seg->use32 = FALSE;
else if (!nasm_stricmp(p, "use32"))
seg->use32 = TRUE;
else if (!nasm_stricmp(p, "flat")) {
/*
* This segment is an OS/2 FLAT segment. That means
* that its default group is group FLAT, even if
* the group FLAT does not explicitly _contain_ the
* segment.
*
* When we see this, we must create the group
* `FLAT', containing no segments, if it does not
* already exist; then we must set the default
* group of this segment to be the FLAT group.
*/
struct Group *grp;
for (grp = grphead; grp; grp = grp->next)
if (!strcmp(grp->name, "FLAT"))
break;
if (!grp) {
obj_directive("group", "FLAT", 1);
for (grp = grphead; grp; grp = grp->next)
if (!strcmp(grp->name, "FLAT"))
break;
if (!grp)
error(ERR_PANIC, "failure to define FLAT?!");
}
seg->grp = grp;
} else if (!nasm_strnicmp(p, "class=", 6))
seg->segclass = nasm_strdup(p + 6);
else if (!nasm_strnicmp(p, "overlay=", 8))
seg->overlay = nasm_strdup(p + 8);
else if (!nasm_strnicmp(p, "align=", 6)) {
seg->align = readnum(p + 6, &rn_error);
if (rn_error) {
seg->align = 1;
error(ERR_NONFATAL, "segment alignment should be"
" numeric");
}
switch ((int)seg->align) {
case 1: /* BYTE */
case 2: /* WORD */
case 4: /* DWORD */
case 16: /* PARA */
case 256: /* PAGE */
case 4096: /* PharLap extension */
break;
case 8:
error(ERR_WARNING,
"OBJ format does not support alignment"
" of 8: rounding up to 16");
seg->align = 16;
break;
case 32:
case 64:
case 128:
error(ERR_WARNING,
"OBJ format does not support alignment"
" of %d: rounding up to 256", seg->align);
seg->align = 256;
break;
case 512:
case 1024:
case 2048:
error(ERR_WARNING,
"OBJ format does not support alignment"
" of %d: rounding up to 4096", seg->align);
seg->align = 4096;
break;
default:
error(ERR_NONFATAL, "invalid alignment value %d",
seg->align);
seg->align = 1;
break;
}
} else if (!nasm_strnicmp(p, "absolute=", 9)) {
seg->align = SEG_ABS + readnum(p + 9, &rn_error);
if (rn_error)
error(ERR_NONFATAL, "argument to `absolute' segment"
" attribute should be numeric");
}
}
/* We need to know whenever we have at least one 32-bit segment */
obj_use32 |= seg->use32;
obj_seg_needs_update = seg;
if (seg->align >= SEG_ABS)
deflabel(name, NO_SEG, seg->align - SEG_ABS,
NULL, FALSE, FALSE, &of_obj, error);
else
deflabel(name, seg->index + 1, 0L,
NULL, FALSE, FALSE, &of_obj, error);
obj_seg_needs_update = NULL;
/*
* See if this segment is defined in any groups.
*/
for (grp = grphead; grp; grp = grp->next) {
for (i = grp->nindices; i < grp->nentries; i++) {
if (!strcmp(grp->segs[i].name, seg->name)) {
nasm_free(grp->segs[i].name);
grp->segs[i] = grp->segs[grp->nindices];
grp->segs[grp->nindices++].index = seg->obj_index;
if (seg->grp)
error(ERR_WARNING,
"segment `%s' is already part of"
" a group: first one takes precedence",
seg->name);
else
seg->grp = grp;
}
}
}
/*
* Walk through the list of externals with unresolved
* default-WRT clauses, and resolve any that point at this
* segment.
*/
extp = &dws;
while (*extp) {
if ((*extp)->defwrt_type == DEFWRT_STRING &&
!strcmp((*extp)->defwrt_ptr.string, seg->name)) {
nasm_free((*extp)->defwrt_ptr.string);
(*extp)->defwrt_type = DEFWRT_SEGMENT;
(*extp)->defwrt_ptr.seg = seg;
*extp = (*extp)->next_dws;
} else
extp = &(*extp)->next_dws;
}
if (seg->use32)
*bits = 32;
else
*bits = 16;
current_seg = seg;
return seg->index;
}
}
static int obj_directive(char *directive, char *value, int pass)
{
if (!strcmp(directive, "group")) {
char *p, *q, *v;
if (pass == 1) {
struct Group *grp;
struct Segment *seg;
struct External **extp;
int obj_idx;
q = value;
while (*q == '.')
q++; /* hack, but a documented one */
v = q;
while (*q && !isspace(*q))
q++;
if (isspace(*q)) {
*q++ = '\0';
while (*q && isspace(*q))
q++;
}
/*
* Here we used to sanity-check the group directive to
* ensure nobody tried to declare a group containing no
* segments. However, OS/2 does this as standard
* practice, so the sanity check has been removed.
*
* if (!*q) {
* error(ERR_NONFATAL,"GROUP directive contains no segments");
* return 1;
* }
*/
obj_idx = 1;
for (grp = grphead; grp; grp = grp->next) {
obj_idx++;
if (!strcmp(grp->name, v)) {
error(ERR_NONFATAL, "group `%s' defined twice", v);
return 1;
}
}
*grptail = grp = nasm_malloc(sizeof(*grp));
grp->next = NULL;
grptail = &grp->next;
grp->index = seg_alloc();
grp->obj_index = obj_idx;
grp->nindices = grp->nentries = 0;
grp->name = NULL;
obj_grp_needs_update = grp;
deflabel(v, grp->index + 1, 0L,
NULL, FALSE, FALSE, &of_obj, error);
obj_grp_needs_update = NULL;
while (*q) {
p = q;
while (*q && !isspace(*q))
q++;
if (isspace(*q)) {
*q++ = '\0';
while (*q && isspace(*q))
q++;
}
/*
* Now p contains a segment name. Find it.
*/
for (seg = seghead; seg; seg = seg->next)
if (!strcmp(seg->name, p))
break;
if (seg) {
/*
* We have a segment index. Shift a name entry
* to the end of the array to make room.
*/
grp->segs[grp->nentries++] = grp->segs[grp->nindices];
grp->segs[grp->nindices++].index = seg->obj_index;
if (seg->grp)
error(ERR_WARNING,
"segment `%s' is already part of"
" a group: first one takes precedence",
seg->name);
else
seg->grp = grp;
} else {
/*
* We have an as-yet undefined segment.
* Remember its name, for later.
*/
grp->segs[grp->nentries++].name = nasm_strdup(p);
}
}
/*
* Walk through the list of externals with unresolved
* default-WRT clauses, and resolve any that point at
* this group.
*/
extp = &dws;
while (*extp) {
if ((*extp)->defwrt_type == DEFWRT_STRING &&
!strcmp((*extp)->defwrt_ptr.string, grp->name)) {
nasm_free((*extp)->defwrt_ptr.string);
(*extp)->defwrt_type = DEFWRT_GROUP;
(*extp)->defwrt_ptr.grp = grp;
*extp = (*extp)->next_dws;
} else
extp = &(*extp)->next_dws;
}
}
return 1;
}
if (!strcmp(directive, "uppercase")) {
obj_uppercase = TRUE;
return 1;
}
if (!strcmp(directive, "import")) {
char *q, *extname, *libname, *impname;
if (pass == 2)
return 1; /* ignore in pass two */
extname = q = value;
while (*q && !isspace(*q))
q++;
if (isspace(*q)) {
*q++ = '\0';
while (*q && isspace(*q))
q++;
}
libname = q;
while (*q && !isspace(*q))
q++;
if (isspace(*q)) {
*q++ = '\0';
while (*q && isspace(*q))
q++;
}
impname = q;
if (!*extname || !*libname)
error(ERR_NONFATAL, "`import' directive requires symbol name"
" and library name");
else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -