2011-11-23 Thomas Klein <th.r.klein@web.de>
[deliverable/binutils-gdb.git] / gas / config / obj-macho.c
CommitLineData
e57f8c65
TG
1/* Mach-O object file format
2 Copyright 2009 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
8 published by the Free Software Foundation; either version 3,
9 or (at your option) any later version.
10
11 GAS is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 the 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 the Free
18 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19 02110-1301, USA. */
20
21#define OBJ_HEADER "obj-macho.h"
22
23#include "as.h"
74a6005f
TG
24#include "subsegs.h"
25#include "symbols.h"
26#include "write.h"
e57f8c65 27#include "mach-o.h"
74a6005f 28#include "mach-o/loader.h"
e57f8c65
TG
29
30static void
31obj_mach_o_weak (int ignore ATTRIBUTE_UNUSED)
32{
33 char *name;
34 int c;
35 symbolS *symbolP;
36
37 do
38 {
39 /* Get symbol name. */
40 name = input_line_pointer;
41 c = get_symbol_end ();
42 symbolP = symbol_find_or_make (name);
43 S_SET_WEAK (symbolP);
44 *input_line_pointer = c;
45 SKIP_WHITESPACE ();
46
47 if (c != ',')
48 break;
49 input_line_pointer++;
50 SKIP_WHITESPACE ();
51 }
52 while (*input_line_pointer != '\n');
53 demand_empty_rest_of_line ();
54}
55
74a6005f
TG
56/* Parse:
57 .section segname,sectname[,type[,attribute[,sizeof_stub]]]
58*/
59
60static void
61obj_mach_o_section (int ignore ATTRIBUTE_UNUSED)
62{
63 char *p;
64 char *segname;
65 char *sectname;
66 char c;
67 int sectype = BFD_MACH_O_S_REGULAR;
68 unsigned int secattr = 0;
69 offsetT sizeof_stub = 0;
70 const char *name;
71 flagword oldflags, flags;
72 asection *sec;
73
74 /* Parse segment name. */
75 if (!is_name_beginner (*input_line_pointer))
76 {
77 as_bad (_("missing segment name"));
78 ignore_rest_of_line ();
79 return;
80 }
81 p = input_line_pointer;
82 c = get_symbol_end ();
83 segname = alloca (input_line_pointer - p + 1);
84 strcpy (segname, p);
85 *input_line_pointer = c;
86
87 if (*input_line_pointer != ',')
88 {
89 as_bad (_("missing comma after segment name"));
90 ignore_rest_of_line ();
91 return;
92 }
93 input_line_pointer++;
94
95 /* Parse section name. */
96 if (!is_name_beginner (*input_line_pointer))
97 {
98 as_bad (_("missing section name"));
99 ignore_rest_of_line ();
100 return;
101 }
102 p = input_line_pointer;
103 c = get_symbol_end ();
104 sectname = alloca (input_line_pointer - p + 1);
105 strcpy (sectname, p);
106 *input_line_pointer = c;
107
108 /* Parse type. */
109 if (*input_line_pointer == ',')
110 {
111 input_line_pointer++;
112 if (!is_name_beginner (*input_line_pointer))
113 {
114 as_bad (_("missing section type name"));
115 ignore_rest_of_line ();
116 return;
117 }
118 p = input_line_pointer;
119 c = get_symbol_end ();
120
121 sectype = bfd_mach_o_get_section_type_from_name (p);
122 if (sectype == -1)
123 {
124 as_bad (_("unknown or invalid section type '%s'"), p);
125 sectype = BFD_MACH_O_S_REGULAR;
126 }
127 *input_line_pointer = c;
128
129 /* Parse attributes. */
130 if (*input_line_pointer == ',')
131 {
132 do
133 {
134 int attr;
135
136 input_line_pointer++;
137
138 if (!is_name_beginner (*input_line_pointer))
139 {
140 as_bad (_("missing section attribute identifier"));
141 ignore_rest_of_line ();
142 break;
143 }
144 p = input_line_pointer;
145 c = get_symbol_end ();
146
147 attr = bfd_mach_o_get_section_attribute_from_name (p);
148 if (attr == -1)
149 as_bad (_("unknown or invalid section attribute '%s'"), p);
150 else
151 secattr |= attr;
152
153 *input_line_pointer = c;
154 }
155 while (*input_line_pointer == '+');
156
157 /* Parse sizeof_stub. */
158 if (*input_line_pointer == ',')
159 {
160 if (sectype != BFD_MACH_O_S_SYMBOL_STUBS)
161 as_bad (_("unexpected sizeof_stub expression"));
162
163 sizeof_stub = get_absolute_expression ();
164 }
165 else if (sectype == BFD_MACH_O_S_SYMBOL_STUBS)
166 as_bad (_("missing sizeof_stub expression"));
167 }
168 }
169 demand_empty_rest_of_line ();
170
171 bfd_mach_o_normalize_section_name (segname, sectname, &name, &flags);
172 if (name == NULL)
173 {
174 /* There is no normal BFD section name for this section. Create one.
175 The name created doesn't really matter as it will never be written
176 on disk. */
177 size_t seglen = strlen (segname);
178 size_t sectlen = strlen (sectname);
179 char *n;
180
181 n = xmalloc (seglen + 1 + sectlen + 1);
182 memcpy (n, segname, seglen);
183 n[seglen] = '.';
184 memcpy (n + seglen + 1, sectname, sectlen);
185 n[seglen + 1 + sectlen] = 0;
186 name = n;
187 }
188
189#ifdef md_flush_pending_output
190 md_flush_pending_output ();
191#endif
192
193 /* Sub-segments don't exists as is on Mach-O. */
194 sec = subseg_new (name, 0);
195
196 oldflags = bfd_get_section_flags (stdoutput, sec);
197 if (oldflags == SEC_NO_FLAGS)
198 {
199 bfd_mach_o_section *msect;
200
201 if (! bfd_set_section_flags (stdoutput, sec, flags))
202 as_warn (_("error setting flags for \"%s\": %s"),
203 bfd_section_name (stdoutput, sec),
204 bfd_errmsg (bfd_get_error ()));
205 msect = bfd_mach_o_get_mach_o_section (sec);
206 strncpy (msect->segname, segname, sizeof (msect->segname));
207 msect->segname[16] = 0;
208 strncpy (msect->sectname, sectname, sizeof (msect->sectname));
209 msect->sectname[16] = 0;
210 msect->flags = secattr | sectype;
211 msect->reserved2 = sizeof_stub;
212 }
213 else if (flags != SEC_NO_FLAGS)
214 {
215 if (flags != oldflags)
216 as_warn (_("Ignoring changed section attributes for %s"), name);
217 }
218}
219
220struct known_section
221{
222 const char *name;
223 unsigned int flags;
224};
225
226static const struct known_section known_sections[] =
227 {
228 /* 0 */ { NULL, 0},
229 /* 1 */ { ".cstring", BFD_MACH_O_S_CSTRING_LITERALS }
230 };
231
232static void
233obj_mach_o_known_section (int sect_index)
234{
235 const struct known_section *sect = &known_sections[sect_index];
236 asection *old_sec;
237 segT sec;
238
239#ifdef md_flush_pending_output
240 md_flush_pending_output ();
241#endif
242
243 old_sec = bfd_get_section_by_name (stdoutput, sect->name);
244 if (old_sec)
245 {
246 /* Section already present. */
247 sec = old_sec;
248 subseg_set (sec, 0);
249 }
250 else
251 {
252 bfd_mach_o_section *msect;
253
254 sec = subseg_force_new (sect->name, 0);
255
256 /* Set default flags. */
257 msect = bfd_mach_o_get_mach_o_section (sec);
258 msect->flags = sect->flags;
259 }
260}
261
262/* Called from read.c:s_comm after we've parsed .comm symbol, size.
263 Parse a possible alignment value. */
264
265static symbolS *
266obj_mach_o_common_parse (int ignore ATTRIBUTE_UNUSED,
267 symbolS *symbolP, addressT size)
268{
269 addressT align = 0;
270
271 if (*input_line_pointer == ',')
272 {
273 align = parse_align (0);
274 if (align == (addressT) -1)
275 return NULL;
276 }
277
278 S_SET_VALUE (symbolP, size);
279 S_SET_EXTERNAL (symbolP);
280 S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
281
282 symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
283
284 return symbolP;
285}
286
287static void
288obj_mach_o_comm (int ignore ATTRIBUTE_UNUSED)
289{
290 s_comm_internal (ignore, obj_mach_o_common_parse);
291}
292
293static void
294obj_mach_o_subsections_via_symbols (int arg ATTRIBUTE_UNUSED)
295{
296 /* Currently ignore it. */
297 demand_empty_rest_of_line ();
298}
299
e57f8c65
TG
300const pseudo_typeS mach_o_pseudo_table[] =
301{
74a6005f
TG
302 { "weak", obj_mach_o_weak, 0},
303 { "section", obj_mach_o_section, 0},
304 { "cstring", obj_mach_o_known_section, 1},
305 { "lcomm", s_lcomm, 1 },
306 { "comm", obj_mach_o_comm, 0 },
307 { "subsections_via_symbols", obj_mach_o_subsections_via_symbols, 0 },
e57f8c65
TG
308
309 {NULL, NULL, 0}
310};
This page took 0.131379 seconds and 4 git commands to generate.