1 /* Mach-O object file format
2 Copyright 2009 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
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.
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.
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
21 #define OBJ_HEADER "obj-macho.h"
28 #include "mach-o/loader.h"
31 obj_mach_o_weak (int ignore ATTRIBUTE_UNUSED
)
39 /* Get symbol name. */
40 name
= input_line_pointer
;
41 c
= get_symbol_end ();
42 symbolP
= symbol_find_or_make (name
);
44 *input_line_pointer
= c
;
52 while (*input_line_pointer
!= '\n');
53 demand_empty_rest_of_line ();
57 .section segname,sectname[,type[,attribute[,sizeof_stub]]]
61 obj_mach_o_section (int ignore ATTRIBUTE_UNUSED
)
67 int sectype
= BFD_MACH_O_S_REGULAR
;
68 unsigned int secattr
= 0;
69 offsetT sizeof_stub
= 0;
71 flagword oldflags
, flags
;
74 /* Parse segment name. */
75 if (!is_name_beginner (*input_line_pointer
))
77 as_bad (_("missing segment name"));
78 ignore_rest_of_line ();
81 p
= input_line_pointer
;
82 c
= get_symbol_end ();
83 segname
= alloca (input_line_pointer
- p
+ 1);
85 *input_line_pointer
= c
;
87 if (*input_line_pointer
!= ',')
89 as_bad (_("missing comma after segment name"));
90 ignore_rest_of_line ();
95 /* Parse section name. */
96 if (!is_name_beginner (*input_line_pointer
))
98 as_bad (_("missing section name"));
99 ignore_rest_of_line ();
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
;
109 if (*input_line_pointer
== ',')
111 input_line_pointer
++;
112 if (!is_name_beginner (*input_line_pointer
))
114 as_bad (_("missing section type name"));
115 ignore_rest_of_line ();
118 p
= input_line_pointer
;
119 c
= get_symbol_end ();
121 sectype
= bfd_mach_o_get_section_type_from_name (p
);
124 as_bad (_("unknown or invalid section type '%s'"), p
);
125 sectype
= BFD_MACH_O_S_REGULAR
;
127 *input_line_pointer
= c
;
129 /* Parse attributes. */
130 if (*input_line_pointer
== ',')
136 input_line_pointer
++;
138 if (!is_name_beginner (*input_line_pointer
))
140 as_bad (_("missing section attribute identifier"));
141 ignore_rest_of_line ();
144 p
= input_line_pointer
;
145 c
= get_symbol_end ();
147 attr
= bfd_mach_o_get_section_attribute_from_name (p
);
149 as_bad (_("unknown or invalid section attribute '%s'"), p
);
153 *input_line_pointer
= c
;
155 while (*input_line_pointer
== '+');
157 /* Parse sizeof_stub. */
158 if (*input_line_pointer
== ',')
160 if (sectype
!= BFD_MACH_O_S_SYMBOL_STUBS
)
161 as_bad (_("unexpected sizeof_stub expression"));
163 sizeof_stub
= get_absolute_expression ();
165 else if (sectype
== BFD_MACH_O_S_SYMBOL_STUBS
)
166 as_bad (_("missing sizeof_stub expression"));
169 demand_empty_rest_of_line ();
171 bfd_mach_o_normalize_section_name (segname
, sectname
, &name
, &flags
);
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
177 size_t seglen
= strlen (segname
);
178 size_t sectlen
= strlen (sectname
);
181 n
= xmalloc (seglen
+ 1 + sectlen
+ 1);
182 memcpy (n
, segname
, seglen
);
184 memcpy (n
+ seglen
+ 1, sectname
, sectlen
);
185 n
[seglen
+ 1 + sectlen
] = 0;
189 #ifdef md_flush_pending_output
190 md_flush_pending_output ();
193 /* Sub-segments don't exists as is on Mach-O. */
194 sec
= subseg_new (name
, 0);
196 oldflags
= bfd_get_section_flags (stdoutput
, sec
);
197 if (oldflags
== SEC_NO_FLAGS
)
199 bfd_mach_o_section
*msect
;
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
;
213 else if (flags
!= SEC_NO_FLAGS
)
215 if (flags
!= oldflags
)
216 as_warn (_("Ignoring changed section attributes for %s"), name
);
226 static const struct known_section known_sections
[] =
229 /* 1 */ { ".cstring", BFD_MACH_O_S_CSTRING_LITERALS
}
233 obj_mach_o_known_section (int sect_index
)
235 const struct known_section
*sect
= &known_sections
[sect_index
];
239 #ifdef md_flush_pending_output
240 md_flush_pending_output ();
243 old_sec
= bfd_get_section_by_name (stdoutput
, sect
->name
);
246 /* Section already present. */
252 bfd_mach_o_section
*msect
;
254 sec
= subseg_force_new (sect
->name
, 0);
256 /* Set default flags. */
257 msect
= bfd_mach_o_get_mach_o_section (sec
);
258 msect
->flags
= sect
->flags
;
262 /* Called from read.c:s_comm after we've parsed .comm symbol, size.
263 Parse a possible alignment value. */
266 obj_mach_o_common_parse (int ignore ATTRIBUTE_UNUSED
,
267 symbolS
*symbolP
, addressT size
)
271 if (*input_line_pointer
== ',')
273 align
= parse_align (0);
274 if (align
== (addressT
) -1)
278 S_SET_VALUE (symbolP
, size
);
279 S_SET_EXTERNAL (symbolP
);
280 S_SET_SEGMENT (symbolP
, bfd_com_section_ptr
);
282 symbol_get_bfdsym (symbolP
)->flags
|= BSF_OBJECT
;
288 obj_mach_o_comm (int ignore ATTRIBUTE_UNUSED
)
290 s_comm_internal (ignore
, obj_mach_o_common_parse
);
294 obj_mach_o_subsections_via_symbols (int arg ATTRIBUTE_UNUSED
)
296 /* Currently ignore it. */
297 demand_empty_rest_of_line ();
300 const pseudo_typeS mach_o_pseudo_table
[] =
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 },