📄 order.c
字号:
bit_16 size;
bit_32 i ;
EndDeclarations
BeginCode
/*+-------------------------------------------------------------------------+
| |
| Compute the address base for the executable image. For .COM files this |
| will be 100H, for .EXE and .SYS files, this will be 0. |
| |
+-------------------------------------------------------------------------+*/
next_available_address = 0L;
If pefile.val IsTrue
Then
// This is buggy- we don't know the size of the header yet, so if they
// make objectAlign too small we have problems...
first_pe_section_address = address_base = imageBase.val + objectAlign.val ;
next_available_address = address_base ; /* no gap */
FLAT_address = address_base ;
Else
If lxfile.val IsTrue OrIf lefile.val IsTrue
Then
first_pe_section_address = address_base = 0 ;
next_available_address = address_base ; /* no gap */
FLAT_address = address_base ;
Else
If comfile.val IsTrue
Then
address_base = 0x100L;
Else
address_base = 0L;
EndIf ;
EndIf
EndIf;
/*+-------------------------------------------------------------------------+
| |
| The ordering expression for the segments must be known. If the |
| "/ORDER:(expression)" switch was specified, then it will be used |
| regardless or whether or not "/DOSSEG" is set. If the "/ORDER" |
| switch was not specified and "/DOSSEG" was, then the appropriate |
| expression is used. Otherwise, the linker will just take the |
| segments in the order they were encountered. |
| |
| update: if use32 is specified we will use a custom ordering that works |
| with the ladsoft tools if no ordering is given |
+-------------------------------------------------------------------------+*/
If ordering.val IsNull
Then
If pefile.val IsTrue
Then
ordering.val = duplicate_string(
string((byte *) ("((cl[*CODE]|cl[*code]|seg[*TEXT]|seg[*text]|cl[*CONST]|cl[*const]),"
" cl[*DATA]|cl[*data]|seg[*DATA]|seg[*data]|"
" ((cl[DGROUP]|cl[dgroup)&!(cl[*BSS]|cl[*bss]));"
" (cl[DGROUP]|cl[dgroup)&(cl[*BSS]|cl[*bss]);cl[*STRING]|cl[*string];"
" cl[INITDATA];cl[EXITDATA];cl[CPPINIT];cl[CPPEXIT],"
" (cl[*BSS]|cl[*bss]|seg[*BSS]|seg[*bss]))")));
Else
If lxfile.val IsTrue OrIf lefile.val IsTrue
Then
ordering.val = duplicate_string(
string((byte *) ("((cl[*CODE]|cl[*code]|seg[*TEXT]|seg[*text]|cl[*CONST]|cl[*const]|cl[*STRING]|cl[*string]),"
" cl[*DATA]|cl[*data]|seg[*DATA]|seg[*data]|"
" ((cl[DGROUP]|cl[dgroup)&!(cl[*BSS]|cl[*bss]));"
" (cl[DGROUP]|cl[dgroup)&(cl[*BSS]|cl[*bss])|"
" cl[INITDATA];cl[EXITDATA];cl[CPPINIT];cl[CPPEXIT],"
" (cl[*BSS]|cl[*bss]|seg[*BSS]|seg[*bss]),"
" (cl[*STACK|cl[*stack]|seg[*STACK]|seg[*stack]))")));
Else If use32.val IsTrue
Then
ordering.val = duplicate_string(
string((byte *) ("(cl[TRAN], cl[STACK], (cl[*CODE]| cl[*code]| seg[*TEXT]| seg[*text]| "
" cl[*CONST]| cl[*const]| cl[*STRING]| cl[*string]| "
" cl[INITDATA]|cl[EXITDATA]|cl[CPPINIT]| cl[CPPEXIT])| "
" ((cl[DGROUP]|cl[dgroup)&!(cl[*BSS]|cl[*bss]))| "
" (cl[DGROUP]|cl[dgroup)&(cl[*BSS]|cl[*bss]))")));
Else If DOSSEG.val IsTrue
Then
ordering.val = duplicate_string(
string((byte *) ("(seg[*code]|seg[*CODE], "
"!(gr[dgroup]|gr[DGROUP]), "
"cl[begdata]|cl[BEGDATA], "
"cl[*data]|cl[*DATA], "
"!(cl[*bss]|cl[*BSS]|cl[*stack]|cl[*STACK]), "
"cl[*bss]|cl[*BSS], "
"cl[*stack]|cl[*STACK])")));
Else
ordering.val = duplicate_string(string((byte *) ("(true)")));
EndIf ;
EndIf;
EndIf ;
EndIf ;
EndIf;
/*+-------------------------------------------------------------------------+
| |
| Check to insure a stack segment of appropriate size is present. For |
| .COM and .SYS files, no stack segment is required. For .EXE files, |
| one is required. For .EXE files, we must insure that a stack of at |
| least the size specified in the "/STACK" switch is available. |
| |
+-------------------------------------------------------------------------+*/
If exefile IsFalse
Then
If stack_segment_found IsTrue
Then
linker_error(4, "Stack segment found for a non .EXE file.\n");
EndIf;
Else
If (stack_segment_found IsFalse) AndIf
(stack.set IsFalse)
Then
If Not pefile.val AndIf Not lxfile.val AndIf Not lefile.val
Then
linker_error(4, "No stack segment for .EXE file.\n");
EndIf ;
Else
If (stack.set IsTrue) AndIf
(Bit_16(Largest_stack_seg.length) LessThan stack.val)
Then
obj_generate_segment(generated_lname,
none_lname,
stack_combine,
2, /* word aligned */
none_lname,
exe_file_list.first,
0L, /* not absolute segment */
Bit_32(stack.val));
EndIf;
EndIf;
EndIf;
/*+-------------------------------------------------------------------------+
| |
| Create a thunk table for imports. We're in catch-22 here because |
| fixups haven't been done so we don't know which symbols are used; but |
| if we don't do this now we won't know how larget the code seg is. |
| we are going to opt to waste space rather than rewrite the linker. |
+-------------------------------------------------------------------------+*/
If pefile.val AndIf n_imports IsNotZero
Then
length = n_imports * 6 ;
lseg = obj_generate_segment(generated_lname,
CODE_lname,
public_combine,
5, /* DWORD aligned */
none_lname,
exe_file_list.first,
0L, /* not absolute segment */
length);
Lseg.highest_uninitialized_byte = length;
import_thunk_table = lseg ;
EndIf
/*+-------------------------------------------------------------------------+
| |
| Handle near communals as follows: If there is at least one near |
| communal, create the segment "c_common" in group "DGROUP" with |
| class "BSS". Then, for each communal place it in "c_common" in |
| ascending order while changing the dictionary entry from |
| "near_communal" to "internal". |
| |
+-------------------------------------------------------------------------+*/
If near_communals IsNotNull
Then
length = 0L;
For pub=near_communals; pub IsNotNull; pub=Pub.Communal.next_communal
BeginFor
LoopIf(Pub.type_entry IsNot near_communal);
length += Pub.Communal.element_size;
EndFor;
If length Exceeds 65536L
Then
linker_error(8, "Near communal size exceeds 64K by %lu bytes.\n",
length-65536L);
EndIf;
lseg = obj_generate_segment(c_common_lname,
BSS_lname,
blank_common_combine,
3, /* paragraph aligned */
none_lname,
exe_file_list.first,
0L, /* not absolute segment */
length);
Lseg.highest_uninitialized_byte = length;
group = lookup_group(DGROUP_lname);
(*Lseg.segment).owning_group = group;
offset = 0;
For pub=near_communals; pub IsNotNull; pub=next_communal
BeginFor
next_communal = Pub.Communal.next_communal;
LoopIf(Pub.type_entry IsNot near_communal);
size = Bit_16(Pub.Communal.element_size);
Pub.type_entry = internal;
Pub.Internal.group = group;
Pub.Internal.lseg = lseg;
Pub.Internal.offset = offset;
Pub.Internal.frame = 0;
offset += size;
EndFor;
EndIf;
/*+-------------------------------------------------------------------------+
| |
| Handle far communals as follows: Packing as many far communals as |
| will fit (64K), create private segments with the segment and class |
| name of "FAR_BSS". They do NOT go in DRGROUP. |
| |
+-------------------------------------------------------------------------+*/
lseg = Null;
offset = 0;
For pub=far_communals; pub IsNotNull; pub=next_communal
BeginFor
next_communal = Pub.Communal.next_communal;
LoopIf(Pub.type_entry IsNot far_communal);
length = Pub.Communal.element_size * Pub.Communal.element_count;
If length Exceeds 65536L
Then
Pub.Communal.next_communal = huge_communals;
huge_communals = pub;
ContinueLoop;
EndIf;
If (lseg IsNull) OrIf ((length + Bit_32(offset)) Exceeds 65536L)
Then
lseg = obj_generate_segment(FAR_BSS_lname,
FAR_BSS_lname,
blank_common_combine,
3, /* paragraph aligned */
none_lname,
exe_file_list.first,
0L, /* not absolute segment */
0L);
offset = 0;
EndIf;
Pub.type_entry = internal;
Pub.Internal.group = Null;
Pub.Internal.lseg = lseg;
Pub.Internal.offset = offset;
Pub.Internal.frame = 0;
offset += Bit_16(length);
Lseg.highest_uninitialized_byte += length;
Lseg.length += length;
(*Lseg.segment).length += length;
EndFor;
/*+-------------------------------------------------------------------------+
| |
| Handle huge communals as follows: Taking as many segments as |
| required, create private segments with the segment and class |
| name of "HUGE_BSS". They do NOT go in DRGROUP. |
| |
+-------------------------------------------------------------------------+*/
For pub=huge_communals; pub IsNotNull; pub=next_communal
BeginFor
next_communal = Pub.Communal.next_communal;
length = Pub.Communal.element_size * Pub.Communal.element_count;
lseg = obj_generate_segment(HUGE_BSS_lname,
HUGE_BSS_lname,
blank_common_combine,
3, /* paragraph aligned */
none_lname,
exe_file_list.first,
0L, /* not absolute segment */
0L);
If Pub.Communal.element_size Exceeds 65536L
Then
linker_error(4, "Communal \"%s\" has element size exceeding 64K.\n",
Pub.symbol);
offset = 0;
Else
offset = Bit_16(65536L Mod Pub.Communal.element_size);
EndIf;
length += Bit_32(offset);
Pub.type_entry = internal;
Pub.Internal.group = Null;
Pub.Internal.lseg = lseg;
Pub.Internal.offset = offset;
Pub.Internal.frame = 0;
Lseg.highest_uninitialized_byte += length;
Lseg.length += length;
(*Lseg.segment).length += length;
EndFor;
return;
EndCode
#undef Pub
#undef Lseg
#undef Group
/*+-------------------------------------------------------------------------+
| |
| order_token_get_char |
| |
+-------------------------------------------------------------------------+*/
void order_token_get_char()
BeginDeclarations
EndDeclarations
BeginCode
If token_break_char Is '\000'
Then
linker_error(8, "Expression syntax error:\n"
"\t\"%s\"\n",
String(ordering.val));
EndIf;
token_break_char = *order_expression_char_ptr++;
return;
EndCode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -