|
|
1.1 root 1: /* sections.c (was subsegs.c in original GAS version)
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GAS, the GNU Assembler.
5:
6: GAS is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 1, or (at your option)
9: any later version.
10:
11: GAS is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GAS; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20: /*
21: * Mach-O sections are chains of fragments.
22: */
23: #include <stdlib.h>
24: #include <strings.h>
25: #include "sections.h"
26: #include "obstack.h"
27: #include "xmalloc.h"
28: #include "frags.h"
29: #include "messages.h"
30:
31: /*
32: * All sections' chains hang off here. NULL means no frchains yet.
33: */
34: frchainS *frchain_root = NULL;
35:
36: /*
37: * The frchain we are assembling into now. That is, the current section's
38: * frag chain, even if it contains no (complete) frags.
39: */
40: frchainS *frchain_now = NULL;
41:
42: /*
43: * sections_begin() sets up to allow sections to be created.
44: */
45: void
46: sections_begin(
47: void)
48: {
49: /* This may be needed if a section_new() for .text is not assumed */
50: /* obstack_begin(&frags, 5000); */
51: /* frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); */
52: }
53:
54: /*
55: * section_new() (for non-zerofill sections) switches to a new section, creating
56: * it if needed, and creates a fresh fragment. If it is the current section
57: * nothing happens except checks to make sure the type, attributes and
58: * sizeof_stub are the same. The segment and section names will be trimed to
59: * fit in the section structure and is the responsiblity of the caller to
60: * report errors if they don't. For zerofill sections only the struct frchain
61: * for the section is returned after possibly being created (these section are
62: * never made the current section and no frags are ever touched).
63: *
64: * Globals on input:
65: * frchain_now points to the (possibly none) struct frchain for the current
66: * section.
67: * frag_now points at an incomplete frag for current section.
68: * If frag_now == NULL, then there is no old, incomplete frag, so the old
69: * frag is not closed off.
70: *
71: * Globals on output:
72: * frchain_now points to the (possibly new) struct frchain for this section.
73: * frchain_root updated if needed (for the first section created).
74: * frag_now is set to the last (possibly new) frag in the section.
75: */
76: frchainS *
77: section_new(
78: char *segname,
79: char *sectname,
80: unsigned long type,
81: unsigned long attributes,
82: unsigned long sizeof_stub)
83: {
84: frchainS *frcP;
85: frchainS **lastPP;
86: unsigned long last_nsect;
87:
88: if(frags.chunk_size == 0)
89: /*
90: * This line is use instead of:
91: * obstack_begin(&frags, 5000);
92: * which the only difference is that frags are allocated on 4 byte
93: * boundaries instead of the default. The problem with the default
94: * is that on some RISC machines the obstack uses 8 (the alignment
95: * of a double after a char in a struct) and then the common use of:
96: * frag_now->fr_fix = obstack_next_free(&frags) -
97: * frag_now->fr_literal;
98: * can get an extra 4 bytes that are not in the frag because of the
99: * 8 byte alignment where only 4 byte alignment for frags are
100: * needed.
101: */
102: _obstack_begin(&frags, 5000, 4,
103: obstack_chunk_alloc, obstack_chunk_free);
104:
105: /*
106: * Determine if this section has been seen.
107: */
108: last_nsect = 0;
109: for(frcP = *(lastPP = &frchain_root);
110: frcP != NULL;
111: frcP = *(lastPP = &frcP->frch_next)){
112: if(strncmp(frcP->frch_section.segname, segname,
113: sizeof(frcP->frch_section.segname)) == 0 &&
114: strncmp(frcP->frch_section.sectname, sectname,
115: sizeof(frcP->frch_section.sectname)) == 0)
116: break;
117: last_nsect = frcP->frch_nsect;
118: }
119:
120: /*
121: * If this section has been seen make sure it's type and attributes
122: * for this call are the same as when the section was created.
123: */
124: if(frcP != NULL){
125: if((frcP->frch_section.flags & SECTION_TYPE) != type){
126: as_warn("section type does not match previous section type");
127: }
128: if(type == S_SYMBOL_STUBS &&
129: frcP->frch_section.reserved2 != sizeof_stub){
130: as_warn("section stub size does not match previous section "
131: "stub size");
132: }
133: if((frcP->frch_section.flags & SECTION_ATTRIBUTES) != attributes){
134: as_warn("section attributes does not match previous section "
135: "attributes");
136: }
137: }
138:
139: /*
140: * If the current section is the same as for this call there is nothing
141: * more to do.
142: */
143: if(frcP != NULL && (frchain_now == frcP || type == S_ZEROFILL)){
144: return(frcP);
145: }
146:
147: /*
148: * For non-zerofill sections it will be made the current section so deal
149: * with the current frag.
150: */
151: if(type != S_ZEROFILL){
152: /*
153: * If there is any current frag in the old section close it off.
154: */
155: if(frag_now != NULL){
156: frag_now->fr_fix = obstack_next_free(&frags) -
157: frag_now->fr_literal;
158: frag_wane(frag_now);
159: }
160:
161: /*
162: * We must do the obstack_finish(), so the next object we put on
163: * obstack frags will not appear to start at the fr_literal of the
164: * current frag. Also, it ensures that the next object will begin
165: * on a address that is aligned correctly for the engine that runs
166: * the assembler.
167: */
168: obstack_finish(&frags);
169: }
170:
171: /*
172: * If this section exists since it is not the current section switch to
173: * it by making it the current chain and create a new frag in it.
174: */
175: if(frcP != NULL){
176: /*
177: * For a zerofill section no frags are created here and since it
178: * exist just return a pointer to the section.
179: */
180: if((frcP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL){
181: return(frcP);
182: }
183: else{
184: /*
185: * Make this section the current section.
186: */
187: frchain_now = frcP;
188:
189: /*
190: * Make a fresh frag for the section.
191: */
192: frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG);
193: memset(frag_now, '\0', SIZEOF_STRUCT_FRAG);
194: frag_now->fr_next = NULL;
195:
196: /*
197: * Append the new frag to the existing frchain.
198: */
199: frchain_now->frch_last->fr_next = frag_now;
200: frchain_now->frch_last = frag_now;
201: }
202: }
203: else{
204: /*
205: * This section does not exist so create a new frchainS struct fill
206: * it in, link it to the chain
207: */
208: frcP = (frchainS *)xmalloc(sizeof(frchainS));
209: memset(frcP, '\0', sizeof(frchainS));
210: strncpy(frcP->frch_section.segname, segname,
211: sizeof(frcP->frch_section.segname));
212: strncpy(frcP->frch_section.sectname, sectname,
213: sizeof(frcP->frch_section.sectname));
214: frcP->frch_section.flags = attributes | type;
215: frcP->frch_section.reserved2 = sizeof_stub;
216:
217: frcP->frch_nsect = last_nsect + 1;
218:
219: *lastPP = frcP;
220:
221: /*
222: * For zerofill sections no frag is created here so just return.
223: * For non-zerofill section create the sections new frag and
224: * make the section the current chain.
225: */
226: if(type == S_ZEROFILL){
227: return(frcP);
228: }
229: else{
230: /*
231: * Make a fresh frag for the new section.
232: */
233: frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG);
234: memset(frag_now, '\0', SIZEOF_STRUCT_FRAG);
235: frag_now->fr_next = NULL;
236:
237: /*
238: * Append the new frag to new frchain.
239: */
240: frcP->frch_root = frag_now;
241: frcP->frch_last = frag_now;
242:
243: /*
244: * Make this section the current section.
245: */
246: frchain_now = frcP;
247: }
248: }
249: return(frchain_now);
250: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.