Fixed reloc generation to match latest opcoide list from cgen.
[deliverable/binutils-gdb.git] / gas / stabs.c
CommitLineData
625f4e48
KR
1/* Generic stabs parsing for gas.
2 Copyright (C) 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
3
4This file is part of GAS, the GNU Assembler.
5
6GAS is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as
8published by the Free Software Foundation; either version 2,
9or (at your option) any later version.
10
11GAS is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14the GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public
17License along with GAS; see the file COPYING. If not, write
18to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "as.h"
c7a89bde 21#include "libiberty.h"
625f4e48
KR
22#include "obstack.h"
23#include "subsegs.h"
24
25/* We need this, despite the apparent object format dependency, since
26 it defines stab types, which all object formats can use now. */
27
28#include "aout/stab_gnu.h"
29
30/* Allow backends to override the names used for the stab sections. */
31#ifndef STAB_SECTION_NAME
32#define STAB_SECTION_NAME ".stab"
33#endif
34
35#ifndef STAB_STRING_SECTION_NAME
36#define STAB_STRING_SECTION_NAME ".stabstr"
37#endif
38
39/*
40 * Handle .stabX directives, which used to be open-coded.
41 * So much creeping featurism overloaded the semantics that we decided
42 * to put all .stabX thinking in one place. Here.
43 *
44 * We try to make any .stabX directive legal. Other people's AS will often
45 * do assembly-time consistency checks: eg assigning meaning to n_type bits
46 * and "protecting" you from setting them to certain values. (They also zero
47 * certain bits before emitting symbols. Tut tut.)
48 *
49 * If an expression is not absolute we either gripe or use the relocation
50 * information. Other people's assemblers silently forget information they
51 * don't need and invent information they need that you didn't supply.
52 */
53
54/*
55 * Build a string dictionary entry for a .stabX symbol.
56 * The symbol is added to the .<secname>str section.
57 */
58
59#ifndef SEPARATE_STAB_SECTIONS
60#define SEPARATE_STAB_SECTIONS 0
61#endif
62
63unsigned int
64get_stab_string_offset (string, stabstr_secname)
65 const char *string;
66 const char *stabstr_secname;
67{
68 unsigned int length;
69 unsigned int retval;
70
71 if (! SEPARATE_STAB_SECTIONS)
72 abort ();
73
74 retval = 0;
75 length = strlen (string);
76 if (length > 0)
77 { /* Ordinary case. */
78 segT save_seg;
79 subsegT save_subseg;
625f4e48
KR
80 segT seg;
81 char *p;
82
83 save_seg = now_seg;
84 save_subseg = now_subseg;
85
86 /* Create the stab string section. */
c7a89bde 87 seg = subseg_new (stabstr_secname, 0);
625f4e48
KR
88
89 retval = seg_info (seg)->stabu.stab_string_size;
c7a89bde 90 if (retval <= 0)
625f4e48
KR
91 {
92 /* Make sure the first string is empty. */
93 p = frag_more (1);
94 *p = 0;
95 retval = seg_info (seg)->stabu.stab_string_size = 1;
96#ifdef BFD_ASSEMBLER
97 bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_DEBUGGING);
c7a89bde
ILT
98 if (seg->name == stabstr_secname)
99 seg->name = xstrdup (stabstr_secname);
625f4e48
KR
100#endif
101 }
102
103 p = frag_more (length + 1);
104 strcpy (p, string);
105
106 seg_info (seg)->stabu.stab_string_size += length + 1;
107
108 subseg_set (save_seg, save_subseg);
109 }
110
111 return retval;
112}
113
114#ifdef AOUT_STABS
115#ifndef OBJ_PROCESS_STAB
116#define OBJ_PROCESS_STAB(SEG,W,S,T,O,D) aout_process_stab(W,S,T,O,D)
117#endif
118
119static void
120aout_process_stab (what, string, type, other, desc)
121 int what;
122 const char *string;
123 int type, other, desc;
124{
125 /* Put the stab information in the symbol table. */
126 symbolS *symbol;
127
128 /* Create the symbol now, but only insert it into the symbol chain
129 after any symbols mentioned in the value expression get into the
130 symbol chain. This is to avoid "continuation symbols" (where one
131 ends in "\" and the debug info is continued in the next .stabs
132 directive) from being separated by other random symbols. */
133 symbol = symbol_create (string, undefined_section, 0,
134 (struct frag *) NULL);
135 if (what == 's' || what == 'n')
136 {
137 /* Pick up the value from the input line. */
138 symbol->sy_frag = &zero_address_frag;
139 pseudo_set (symbol);
140 }
141 else
142 {
143 /* .stabd sets the name to NULL. Why? */
144 S_SET_NAME (symbol, NULL);
145 symbol->sy_frag = frag_now;
146 S_SET_VALUE (symbol, (valueT) frag_now_fix ());
147 }
148
149 symbol_append (symbol, symbol_lastP, &symbol_rootP, &symbol_lastP);
150
151 S_SET_TYPE (symbol, type);
152 S_SET_OTHER (symbol, other);
153 S_SET_DESC (symbol, desc);
154}
155#endif
156
157/* This can handle different kinds of stabs (s,n,d) and different
158 kinds of stab sections. */
159
160static void
161s_stab_generic (what, stab_secname, stabstr_secname)
162 int what;
163 char *stab_secname;
164 char *stabstr_secname;
165{
166 long longint;
167 char *string;
168 int type;
169 int other;
170 int desc;
171
172 /* The general format is:
173 .stabs "STRING",TYPE,OTHER,DESC,VALUE
174 .stabn TYPE,OTHER,DESC,VALUE
175 .stabd TYPE,OTHER,DESC
176 At this point input_line_pointer points after the pseudo-op and
177 any trailing whitespace. The argument what is one of 's', 'n' or
178 'd' indicating which type of .stab this is. */
179
180 if (what != 's')
181 string = "";
182 else
183 {
184 int length;
185
186 string = demand_copy_C_string (&length);
187 SKIP_WHITESPACE ();
188 if (*input_line_pointer == ',')
189 input_line_pointer++;
190 else
191 {
192 as_warn (".stabs: Missing comma");
193 ignore_rest_of_line ();
194 return;
195 }
196 }
197
198 if (get_absolute_expression_and_terminator (&longint) != ',')
199 {
200 as_warn (".stab%c: Missing comma", what);
201 ignore_rest_of_line ();
202 return;
203 }
204 type = longint;
205
206 if (get_absolute_expression_and_terminator (&longint) != ',')
207 {
208 as_warn (".stab%c: Missing comma", what);
209 ignore_rest_of_line ();
210 return;
211 }
212 other = longint;
213
214 desc = get_absolute_expression ();
215 if (what == 's' || what == 'n')
216 {
217 if (*input_line_pointer != ',')
218 {
219 as_warn (".stab%c: Missing comma", what);
220 ignore_rest_of_line ();
221 return;
222 }
223 input_line_pointer++;
224 SKIP_WHITESPACE ();
225 }
226
63cafcef
MM
227#ifdef TC_PPC
228#ifdef OBJ_ELF
229 /* Solaris on PowerPC has decided that .stabd takes 4 arguments, so emulate it. */
230 else if (what == 'd')
231 {
232 char *save_location = input_line_pointer;
233
234 SKIP_WHITESPACE ();
235 if (*input_line_pointer == ',')
236 {
237 int dummy;
238
239 input_line_pointer++;
240 SKIP_WHITESPACE ();
241
242 dummy = get_absolute_expression ();
243 if (dummy != 0)
244 {
245 as_warn (".stabd: Fourth field must be 0");
246 ignore_rest_of_line ();
247 return;
248 }
249 SKIP_WHITESPACE ();
250 }
251 else
252 input_line_pointer = save_location;
253 }
254#endif /* OBJ_ELF */
255#endif /* TC_PPC */
256
257#ifndef NO_LISTING
258 if (listing)
259 {
260 switch (type)
261 {
262 case N_SLINE:
263 listing_source_line ((unsigned int) desc);
264 break;
265 case N_SO:
266 case N_SOL:
267 listing_source_file (string);
268 break;
269 }
270 }
271#endif /* ! NO_LISTING */
272
625f4e48
KR
273 /* We have now gathered the type, other, and desc information. For
274 .stabs or .stabn, input_line_pointer is now pointing at the
275 value. */
276
277 if (SEPARATE_STAB_SECTIONS)
278 /* Output the stab information in a separate section. This is used
279 at least for COFF and ELF. */
280 {
281 segT saved_seg = now_seg;
282 subsegT saved_subseg = now_subseg;
283 fragS *saved_frag = frag_now;
284 valueT dot;
285 segT seg;
286 unsigned int stroff;
287 char *p;
288
c7a89bde
ILT
289 static segT cached_sec;
290 static char *cached_secname;
291
625f4e48
KR
292 dot = frag_now_fix ();
293
c7a89bde
ILT
294 if (cached_secname && !strcmp (cached_secname, stab_secname))
295 {
296 seg = cached_sec;
297 subseg_set (seg, 0);
298 }
299 else
300 {
301 seg = subseg_new (stab_secname, 0);
302 if (cached_secname)
303 free (cached_secname);
304 cached_secname = xstrdup (stab_secname);
305 cached_sec = seg;
306 }
625f4e48
KR
307
308 if (! seg_info (seg)->hadone)
309 {
310#ifdef BFD_ASSEMBLER
311 bfd_set_section_flags (stdoutput, seg,
312 SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
313#endif
314#ifdef INIT_STAB_SECTION
315 INIT_STAB_SECTION (seg);
316#endif
317 seg_info (seg)->hadone = 1;
318 }
319
320 stroff = get_stab_string_offset (string, stabstr_secname);
c7a89bde
ILT
321 if (what == 's')
322 {
323 /* release the string */
324 obstack_free (&notes, string);
325 }
625f4e48
KR
326
327 /* At least for now, stabs in a special stab section are always
328 output as 12 byte blocks of information. */
329 p = frag_more (8);
330 md_number_to_chars (p, (valueT) stroff, 4);
331 md_number_to_chars (p + 4, (valueT) type, 1);
332 md_number_to_chars (p + 5, (valueT) other, 1);
333 md_number_to_chars (p + 6, (valueT) desc, 2);
334
335 if (what == 's' || what == 'n')
336 {
337 /* Pick up the value from the input line. */
338 cons (4);
339 input_line_pointer--;
340 }
341 else
342 {
343 const char *fake;
344 symbolS *symbol;
345 expressionS exp;
346
347 /* Arrange for a value representing the current location. */
348 fake = FAKE_LABEL_NAME;
349 symbol = symbol_new (fake, saved_seg, dot, saved_frag);
350
351 exp.X_op = O_symbol;
352 exp.X_add_symbol = symbol;
353 exp.X_add_number = 0;
354
355 emit_expr (&exp, 4);
356 }
357
358#ifdef OBJ_PROCESS_STAB
63cafcef 359 OBJ_PROCESS_STAB (seg, what, string, type, other, desc);
625f4e48
KR
360#endif
361
362 subseg_set (saved_seg, saved_subseg);
363 }
364 else
365 {
366#ifdef OBJ_PROCESS_STAB
367 OBJ_PROCESS_STAB (0, what, string, type, other, desc);
368#else
369 abort ();
370#endif
371 }
372
625f4e48
KR
373 demand_empty_rest_of_line ();
374}
375
376/* Regular stab directive. */
377
378void
379s_stab (what)
380 int what;
381{
382 s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME);
383}
384
385/* "Extended stabs", used in Solaris only now. */
386
387void
388s_xstab (what)
389 int what;
390{
391 int length;
392 char *stab_secname, *stabstr_secname;
c7a89bde 393 static char *saved_secname, *saved_strsecname;
625f4e48 394
c7a89bde
ILT
395 /* @@ MEMORY LEAK: This allocates a copy of the string, but in most
396 cases it will be the same string, so we could release the storage
397 back to the obstack it came from. */
625f4e48
KR
398 stab_secname = demand_copy_C_string (&length);
399 SKIP_WHITESPACE ();
400 if (*input_line_pointer == ',')
401 input_line_pointer++;
402 else
403 {
404 as_bad ("comma missing in .xstabs");
405 ignore_rest_of_line ();
406 return;
407 }
408
409 /* To get the name of the stab string section, simply add "str" to
410 the stab section name. */
c7a89bde
ILT
411 if (saved_secname == 0 || strcmp (saved_secname, stab_secname))
412 {
413 stabstr_secname = (char *) xmalloc (strlen (stab_secname) + 4);
414 strcpy (stabstr_secname, stab_secname);
415 strcat (stabstr_secname, "str");
416 if (saved_secname)
417 {
418 free (saved_secname);
419 free (saved_strsecname);
420 }
421 saved_secname = stab_secname;
422 saved_strsecname = stabstr_secname;
423 }
424 s_stab_generic (what, saved_secname, saved_strsecname);
625f4e48
KR
425}
426
427#ifdef S_SET_DESC
428
429/* Frob invented at RMS' request. Set the n_desc of a symbol. */
430
431void
432s_desc (ignore)
433 int ignore;
434{
435 char *name;
436 char c;
437 char *p;
438 symbolS *symbolP;
439 int temp;
440
441 name = input_line_pointer;
442 c = get_symbol_end ();
443 p = input_line_pointer;
444 *p = c;
445 SKIP_WHITESPACE ();
446 if (*input_line_pointer != ',')
447 {
448 *p = 0;
449 as_bad ("Expected comma after name \"%s\"", name);
450 *p = c;
451 ignore_rest_of_line ();
452 }
453 else
454 {
455 input_line_pointer++;
456 temp = get_absolute_expression ();
457 *p = 0;
458 symbolP = symbol_find_or_make (name);
459 *p = c;
460 S_SET_DESC (symbolP, temp);
461 }
462 demand_empty_rest_of_line ();
463} /* s_desc() */
464
465#endif /* defined (S_SET_DESC) */
This page took 0.143982 seconds and 4 git commands to generate.