12159047fSniklas /* subsegs.c - subsegments -
2b55d4692Sfgsch Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3c074d1c9Sdrahn 1999, 2000, 2002
42159047fSniklas Free Software Foundation, Inc.
52159047fSniklas
62159047fSniklas This file is part of GAS, the GNU Assembler.
72159047fSniklas
82159047fSniklas GAS is free software; you can redistribute it and/or modify
92159047fSniklas it under the terms of the GNU General Public License as published by
102159047fSniklas the Free Software Foundation; either version 2, or (at your option)
112159047fSniklas any later version.
122159047fSniklas
132159047fSniklas GAS is distributed in the hope that it will be useful,
142159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
162159047fSniklas GNU General Public License for more details.
172159047fSniklas
182159047fSniklas You should have received a copy of the GNU General Public License
190c6d0228Sniklas along with GAS; see the file COPYING. If not, write to the Free
200c6d0228Sniklas Software Foundation, 59 Temple Place - Suite 330, Boston, MA
210c6d0228Sniklas 02111-1307, USA. */
222159047fSniklas
23b55d4692Sfgsch /* Segments & sub-segments. */
242159047fSniklas
252159047fSniklas #include "as.h"
262159047fSniklas
272159047fSniklas #include "subsegs.h"
282159047fSniklas #include "obstack.h"
292159047fSniklas
302159047fSniklas frchainS *frchain_root, *frchain_now;
312159047fSniklas
322159047fSniklas static struct obstack frchains;
332159047fSniklas
342159047fSniklas #ifndef BFD_ASSEMBLER
352159047fSniklas #ifdef MANY_SEGMENTS
362159047fSniklas segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
372159047fSniklas
382159047fSniklas #else
392159047fSniklas /* Commented in "subsegs.h". */
402159047fSniklas frchainS *data0_frchainP, *bss0_frchainP;
412159047fSniklas
422159047fSniklas #endif /* MANY_SEGMENTS */
43b55d4692Sfgsch char const *const seg_name[] = {
442159047fSniklas "absolute",
452159047fSniklas #ifdef MANY_SEGMENTS
462159047fSniklas "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
47191aa565Sniklas "e10", "e11", "e12", "e13", "e14", "e15", "e16", "e17", "e18", "e19",
48191aa565Sniklas "e20", "e21", "e22", "e23", "e24", "e25", "e26", "e27", "e28", "e29",
49191aa565Sniklas "e30", "e31", "e32", "e33", "e34", "e35", "e36", "e37", "e38", "e39",
502159047fSniklas #else
512159047fSniklas "text",
522159047fSniklas "data",
532159047fSniklas "bss",
542159047fSniklas #endif /* MANY_SEGMENTS */
552159047fSniklas "unknown",
562159047fSniklas "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
572159047fSniklas "expr",
582159047fSniklas "debug",
592159047fSniklas "transfert vector preload",
602159047fSniklas "transfert vector postload",
612159047fSniklas "register",
622159047fSniklas "",
632159047fSniklas }; /* Used by error reporters, dumpers etc. */
642159047fSniklas #else /* BFD_ASSEMBLER */
652159047fSniklas
662159047fSniklas /* Gas segment information for bfd_abs_section_ptr and
672159047fSniklas bfd_und_section_ptr. */
682159047fSniklas static segment_info_type *abs_seg_info;
692159047fSniklas static segment_info_type *und_seg_info;
702159047fSniklas
712159047fSniklas #endif /* BFD_ASSEMBLER */
722159047fSniklas
73*007c2a45Smiod static void subseg_set_rest (segT, subsegT);
742159047fSniklas
752159047fSniklas static fragS dummy_frag;
762159047fSniklas
772159047fSniklas static frchainS absolute_frchain;
782159047fSniklas
792159047fSniklas void
subsegs_begin(void)80*007c2a45Smiod subsegs_begin (void)
812159047fSniklas {
822159047fSniklas /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
832159047fSniklas #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
842159047fSniklas know (SEG_ABSOLUTE == 0);
852159047fSniklas know (SEG_TEXT == 1);
862159047fSniklas know (SEG_DATA == 2);
872159047fSniklas know (SEG_BSS == 3);
882159047fSniklas know (SEG_UNKNOWN == 4);
892159047fSniklas know (SEG_GOOF == 5);
902159047fSniklas know (SEG_EXPR == 6);
912159047fSniklas know (SEG_DEBUG == 7);
922159047fSniklas know (SEG_NTV == 8);
932159047fSniklas know (SEG_PTV == 9);
942159047fSniklas know (SEG_REGISTER == 10);
952159047fSniklas know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
962159047fSniklas #endif
972159047fSniklas
982159047fSniklas obstack_begin (&frchains, chunksize);
992159047fSniklas #if __GNUC__ >= 2
1002159047fSniklas obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
1012159047fSniklas #endif
1022159047fSniklas
1032159047fSniklas frchain_root = NULL;
1042159047fSniklas frchain_now = NULL; /* Warn new_subseg() that we are booting. */
1052159047fSniklas
1062159047fSniklas frag_now = &dummy_frag;
1072159047fSniklas
1082159047fSniklas #ifndef BFD_ASSEMBLER
1092159047fSniklas now_subseg = 42; /* Lie for 1st call to subseg_new. */
1102159047fSniklas #ifdef MANY_SEGMENTS
1112159047fSniklas {
1122159047fSniklas int i;
1132159047fSniklas for (i = SEG_E0; i < SEG_UNKNOWN; i++)
1142159047fSniklas {
1152159047fSniklas subseg_set (i, 0);
1162159047fSniklas segment_info[i].frchainP = frchain_now;
1172159047fSniklas }
1182159047fSniklas }
1192159047fSniklas #else
1202159047fSniklas subseg_set (SEG_DATA, 0); /* .data 0 */
1212159047fSniklas data0_frchainP = frchain_now;
1222159047fSniklas
1232159047fSniklas subseg_set (SEG_BSS, 0);
1242159047fSniklas bss0_frchainP = frchain_now;
1252159047fSniklas
1262159047fSniklas #endif /* ! MANY_SEGMENTS */
1272159047fSniklas #endif /* ! BFD_ASSEMBLER */
1282159047fSniklas
1292159047fSniklas absolute_frchain.frch_seg = absolute_section;
1302159047fSniklas absolute_frchain.frch_subseg = 0;
1312159047fSniklas #ifdef BFD_ASSEMBLER
1322159047fSniklas absolute_frchain.fix_root = absolute_frchain.fix_tail = 0;
1332159047fSniklas #endif
1342159047fSniklas absolute_frchain.frch_frag_now = &zero_address_frag;
1352159047fSniklas absolute_frchain.frch_root = absolute_frchain.frch_last = &zero_address_frag;
1362159047fSniklas }
1372159047fSniklas
1382159047fSniklas /*
1392159047fSniklas * subseg_change()
1402159047fSniklas *
1412159047fSniklas * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
1422159047fSniklas * subsegment. If we are already in the correct subsegment, change nothing.
1432159047fSniklas * This is used eg as a worker for subseg_set [which does make a new frag_now]
1442159047fSniklas * and for changing segments after we have read the source. We construct eg
1452159047fSniklas * fixSs even after the source file is read, so we do have to keep the
1462159047fSniklas * segment context correct.
1472159047fSniklas */
1482159047fSniklas void
subseg_change(register segT seg,register int subseg)149*007c2a45Smiod subseg_change (register segT seg, register int subseg)
1502159047fSniklas {
1512159047fSniklas now_seg = seg;
1522159047fSniklas now_subseg = subseg;
1532159047fSniklas
1542159047fSniklas if (now_seg == absolute_section)
1552159047fSniklas return;
1562159047fSniklas
1572159047fSniklas #ifdef BFD_ASSEMBLER
1582159047fSniklas {
1592159047fSniklas segment_info_type *seginfo;
1602159047fSniklas seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
1612159047fSniklas if (! seginfo)
1622159047fSniklas {
1632159047fSniklas seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
1642159047fSniklas memset ((PTR) seginfo, 0, sizeof (*seginfo));
1652159047fSniklas seginfo->fix_root = NULL;
1662159047fSniklas seginfo->fix_tail = NULL;
1672159047fSniklas seginfo->bfd_section = seg;
1682159047fSniklas seginfo->sym = 0;
1692159047fSniklas if (seg == bfd_abs_section_ptr)
1702159047fSniklas abs_seg_info = seginfo;
1712159047fSniklas else if (seg == bfd_und_section_ptr)
1722159047fSniklas und_seg_info = seginfo;
1732159047fSniklas else
1742159047fSniklas bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
1752159047fSniklas }
1762159047fSniklas }
1772159047fSniklas #else
1782159047fSniklas #ifdef MANY_SEGMENTS
1792159047fSniklas seg_fix_rootP = &segment_info[seg].fix_root;
1802159047fSniklas seg_fix_tailP = &segment_info[seg].fix_tail;
1812159047fSniklas #else
1822159047fSniklas if (seg == SEG_DATA)
1832159047fSniklas {
1842159047fSniklas seg_fix_rootP = &data_fix_root;
1852159047fSniklas seg_fix_tailP = &data_fix_tail;
1862159047fSniklas }
1872159047fSniklas else if (seg == SEG_TEXT)
1882159047fSniklas {
1892159047fSniklas seg_fix_rootP = &text_fix_root;
1902159047fSniklas seg_fix_tailP = &text_fix_tail;
1912159047fSniklas }
1922159047fSniklas else
1932159047fSniklas {
1942159047fSniklas know (seg == SEG_BSS);
1952159047fSniklas seg_fix_rootP = &bss_fix_root;
1962159047fSniklas seg_fix_tailP = &bss_fix_tail;
1972159047fSniklas }
1982159047fSniklas
1992159047fSniklas #endif
2002159047fSniklas #endif
2012159047fSniklas }
2022159047fSniklas
2032159047fSniklas static void
subseg_set_rest(segT seg,subsegT subseg)204*007c2a45Smiod subseg_set_rest (segT seg, subsegT subseg)
2052159047fSniklas {
2062159047fSniklas register frchainS *frcP; /* crawl frchain chain */
2072159047fSniklas register frchainS **lastPP; /* address of last pointer */
2082159047fSniklas frchainS *newP; /* address of new frchain */
2092159047fSniklas
2102159047fSniklas mri_common_symbol = NULL;
2112159047fSniklas
2122159047fSniklas if (frag_now && frchain_now)
2132159047fSniklas frchain_now->frch_frag_now = frag_now;
2142159047fSniklas
2152159047fSniklas assert (frchain_now == 0
2162159047fSniklas || now_seg == undefined_section
2172159047fSniklas || now_seg == absolute_section
2182159047fSniklas || frchain_now->frch_last == frag_now);
2192159047fSniklas
2202159047fSniklas subseg_change (seg, (int) subseg);
2212159047fSniklas
2222159047fSniklas if (seg == absolute_section)
2232159047fSniklas {
2242159047fSniklas frchain_now = &absolute_frchain;
2252159047fSniklas frag_now = &zero_address_frag;
2262159047fSniklas return;
2272159047fSniklas }
2282159047fSniklas
2292159047fSniklas assert (frchain_now == 0
2302159047fSniklas || now_seg == undefined_section
2312159047fSniklas || frchain_now->frch_last == frag_now);
2322159047fSniklas
2332159047fSniklas /*
2342159047fSniklas * Attempt to find or make a frchain for that sub seg.
2352159047fSniklas * Crawl along chain of frchainSs, begins @ frchain_root.
2362159047fSniklas * If we need to make a frchainS, link it into correct
2372159047fSniklas * position of chain rooted in frchain_root.
2382159047fSniklas */
2392159047fSniklas for (frcP = *(lastPP = &frchain_root);
2402159047fSniklas frcP && frcP->frch_seg <= seg;
2412159047fSniklas frcP = *(lastPP = &frcP->frch_next))
2422159047fSniklas {
2432159047fSniklas if (frcP->frch_seg == seg
2442159047fSniklas && frcP->frch_subseg >= subseg)
2452159047fSniklas {
2462159047fSniklas break;
2472159047fSniklas }
2482159047fSniklas }
2492159047fSniklas /*
2502159047fSniklas * frcP: Address of the 1st frchainS in correct segment with
2512159047fSniklas * frch_subseg >= subseg.
2522159047fSniklas * We want to either use this frchainS, or we want
2532159047fSniklas * to insert a new frchainS just before it.
2542159047fSniklas *
2552159047fSniklas * If frcP==NULL, then we are at the end of the chain
2562159047fSniklas * of frchainS-s. A NULL frcP means we fell off the end
2572159047fSniklas * of the chain looking for a
2582159047fSniklas * frch_subseg >= subseg, so we
2592159047fSniklas * must make a new frchainS.
2602159047fSniklas *
2612159047fSniklas * If we ever maintain a pointer to
2622159047fSniklas * the last frchainS in the chain, we change that pointer
2632159047fSniklas * ONLY when frcP==NULL.
2642159047fSniklas *
2652159047fSniklas * lastPP: Address of the pointer with value frcP;
2662159047fSniklas * Never NULL.
2672159047fSniklas * May point to frchain_root.
2682159047fSniklas *
2692159047fSniklas */
2702159047fSniklas if (!frcP
2712159047fSniklas || (frcP->frch_seg > seg
2722159047fSniklas || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
2732159047fSniklas {
2742159047fSniklas /*
2752159047fSniklas * This should be the only code that creates a frchainS.
2762159047fSniklas */
2772159047fSniklas newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
2782159047fSniklas newP->frch_subseg = subseg;
2792159047fSniklas newP->frch_seg = seg;
2802159047fSniklas #ifdef BFD_ASSEMBLER
2812159047fSniklas newP->fix_root = NULL;
2822159047fSniklas newP->fix_tail = NULL;
2832159047fSniklas #endif
284b305b0f1Sespie obstack_begin (&newP->frch_obstack, chunksize);
2852159047fSniklas #if __GNUC__ >= 2
2862159047fSniklas obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
2872159047fSniklas #endif
2882159047fSniklas newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
2892159047fSniklas newP->frch_frag_now->fr_type = rs_fill;
2902159047fSniklas
2912159047fSniklas newP->frch_root = newP->frch_last = newP->frch_frag_now;
2922159047fSniklas
2932159047fSniklas *lastPP = newP;
2942159047fSniklas newP->frch_next = frcP; /* perhaps NULL */
295b305b0f1Sespie
296b305b0f1Sespie #ifdef BFD_ASSEMBLER
297b305b0f1Sespie {
298b305b0f1Sespie segment_info_type *seginfo;
299b305b0f1Sespie seginfo = seg_info (seg);
300b305b0f1Sespie if (seginfo && seginfo->frchainP == frcP)
301b305b0f1Sespie seginfo->frchainP = newP;
302b305b0f1Sespie }
303b305b0f1Sespie #endif
304b305b0f1Sespie
3052159047fSniklas frcP = newP;
3062159047fSniklas }
3072159047fSniklas /*
3082159047fSniklas * Here with frcP pointing to the frchainS for subseg.
3092159047fSniklas */
3102159047fSniklas frchain_now = frcP;
3112159047fSniklas frag_now = frcP->frch_frag_now;
3122159047fSniklas
3132159047fSniklas assert (frchain_now->frch_last == frag_now);
3142159047fSniklas }
3152159047fSniklas
3162159047fSniklas /*
3172159047fSniklas * subseg_set(segT, subsegT)
3182159047fSniklas *
3192159047fSniklas * If you attempt to change to the current subsegment, nothing happens.
3202159047fSniklas *
3212159047fSniklas * In: segT, subsegT code for new subsegment.
3222159047fSniklas * frag_now -> incomplete frag for current subsegment.
3232159047fSniklas * If frag_now==NULL, then there is no old, incomplete frag, so
3242159047fSniklas * the old frag is not closed off.
3252159047fSniklas *
3262159047fSniklas * Out: now_subseg, now_seg updated.
3272159047fSniklas * Frchain_now points to the (possibly new) struct frchain for this
3282159047fSniklas * sub-segment.
3292159047fSniklas * Frchain_root updated if needed.
3302159047fSniklas */
3312159047fSniklas
3322159047fSniklas #ifndef BFD_ASSEMBLER
3332159047fSniklas
3342159047fSniklas segT
subseg_new(segname,subseg)3352159047fSniklas subseg_new (segname, subseg)
3362159047fSniklas const char *segname;
3372159047fSniklas subsegT subseg;
3382159047fSniklas {
3392159047fSniklas int i;
3402159047fSniklas
3412159047fSniklas for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
3422159047fSniklas {
3432159047fSniklas const char *s;
3442159047fSniklas
3452159047fSniklas s = segment_name ((segT) i);
3462159047fSniklas if (strcmp (segname, s) == 0
3472159047fSniklas || (segname[0] == '.'
3482159047fSniklas && strcmp (segname + 1, s) == 0))
3492159047fSniklas {
3502159047fSniklas subseg_set ((segT) i, subseg);
3512159047fSniklas return (segT) i;
3522159047fSniklas }
3532159047fSniklas #ifdef obj_segment_name
3542159047fSniklas s = obj_segment_name ((segT) i);
3552159047fSniklas if (strcmp (segname, s) == 0
3562159047fSniklas || (segname[0] == '.'
3572159047fSniklas && strcmp (segname + 1, s) == 0))
3582159047fSniklas {
3592159047fSniklas subseg_set ((segT) i, subseg);
3602159047fSniklas return (segT) i;
3612159047fSniklas }
3622159047fSniklas #endif
3632159047fSniklas }
3642159047fSniklas
3652159047fSniklas #ifdef obj_add_segment
3662159047fSniklas {
3672159047fSniklas segT new_seg;
3682159047fSniklas new_seg = obj_add_segment (segname);
3692159047fSniklas subseg_set (new_seg, subseg);
3702159047fSniklas return new_seg;
3712159047fSniklas }
3722159047fSniklas #else
373c074d1c9Sdrahn as_bad (_("attempt to switch to nonexistent segment \"%s\""), segname);
3742159047fSniklas return now_seg;
3752159047fSniklas #endif
3762159047fSniklas }
3772159047fSniklas
3782159047fSniklas void
subseg_set(seg,subseg)3792159047fSniklas subseg_set (seg, subseg) /* begin assembly for a new sub-segment */
3802159047fSniklas register segT seg; /* SEG_DATA or SEG_TEXT */
3812159047fSniklas register subsegT subseg;
3822159047fSniklas {
3832159047fSniklas #ifndef MANY_SEGMENTS
3842159047fSniklas know (seg == SEG_DATA
3852159047fSniklas || seg == SEG_TEXT
3862159047fSniklas || seg == SEG_BSS
3872159047fSniklas || seg == SEG_ABSOLUTE);
3882159047fSniklas #endif
3892159047fSniklas
3902159047fSniklas if (seg != now_seg || subseg != now_subseg)
3912159047fSniklas { /* we just changed sub-segments */
3922159047fSniklas subseg_set_rest (seg, subseg);
3932159047fSniklas }
3942159047fSniklas mri_common_symbol = NULL;
3952159047fSniklas }
3962159047fSniklas
3972159047fSniklas #else /* BFD_ASSEMBLER */
3982159047fSniklas
3992159047fSniklas segT
subseg_get(const char * segname,int force_new)400*007c2a45Smiod subseg_get (const char *segname, int force_new)
4012159047fSniklas {
4022159047fSniklas segT secptr;
4032159047fSniklas segment_info_type *seginfo;
4042159047fSniklas const char *now_seg_name = (now_seg
4052159047fSniklas ? bfd_get_section_name (stdoutput, now_seg)
4062159047fSniklas : 0);
4072159047fSniklas
4082159047fSniklas if (!force_new
4092159047fSniklas && now_seg_name
4102159047fSniklas && (now_seg_name == segname
4112159047fSniklas || !strcmp (now_seg_name, segname)))
4122159047fSniklas return now_seg;
4132159047fSniklas
4142159047fSniklas if (!force_new)
4152159047fSniklas secptr = bfd_make_section_old_way (stdoutput, segname);
4162159047fSniklas else
4172159047fSniklas secptr = bfd_make_section_anyway (stdoutput, segname);
4182159047fSniklas
419*007c2a45Smiod #ifdef obj_sec_set_private_data
420*007c2a45Smiod obj_sec_set_private_data (stdoutput, secptr);
421*007c2a45Smiod #endif
422*007c2a45Smiod
4232159047fSniklas seginfo = seg_info (secptr);
4242159047fSniklas if (! seginfo)
4252159047fSniklas {
4262159047fSniklas /* Check whether output_section is set first because secptr may
4272159047fSniklas be bfd_abs_section_ptr. */
4282159047fSniklas if (secptr->output_section != secptr)
4292159047fSniklas secptr->output_section = secptr;
4302159047fSniklas seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
4312159047fSniklas memset ((PTR) seginfo, 0, sizeof (*seginfo));
4322159047fSniklas seginfo->fix_root = NULL;
4332159047fSniklas seginfo->fix_tail = NULL;
4342159047fSniklas seginfo->bfd_section = secptr;
4352159047fSniklas if (secptr == bfd_abs_section_ptr)
4362159047fSniklas abs_seg_info = seginfo;
4372159047fSniklas else if (secptr == bfd_und_section_ptr)
4382159047fSniklas und_seg_info = seginfo;
4392159047fSniklas else
4402159047fSniklas bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
4412159047fSniklas seginfo->frchainP = NULL;
4422159047fSniklas seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
4432159047fSniklas seginfo->sym = NULL;
4442159047fSniklas seginfo->dot = NULL;
4452159047fSniklas }
4462159047fSniklas return secptr;
4472159047fSniklas }
4482159047fSniklas
4492159047fSniklas segT
subseg_new(const char * segname,subsegT subseg)450*007c2a45Smiod subseg_new (const char *segname, subsegT subseg)
4512159047fSniklas {
4522159047fSniklas segT secptr;
4532159047fSniklas segment_info_type *seginfo;
4542159047fSniklas
4552159047fSniklas secptr = subseg_get (segname, 0);
4562159047fSniklas subseg_set_rest (secptr, subseg);
4572159047fSniklas seginfo = seg_info (secptr);
4582159047fSniklas if (! seginfo->frchainP)
4592159047fSniklas seginfo->frchainP = frchain_now;
4602159047fSniklas return secptr;
4612159047fSniklas }
4622159047fSniklas
4632159047fSniklas /* Like subseg_new, except a new section is always created, even if
4642159047fSniklas a section with that name already exists. */
4652159047fSniklas segT
subseg_force_new(const char * segname,subsegT subseg)466*007c2a45Smiod subseg_force_new (const char *segname, subsegT subseg)
4672159047fSniklas {
4682159047fSniklas segT secptr;
4692159047fSniklas segment_info_type *seginfo;
4702159047fSniklas
4712159047fSniklas secptr = subseg_get (segname, 1);
4722159047fSniklas subseg_set_rest (secptr, subseg);
4732159047fSniklas seginfo = seg_info (secptr);
4742159047fSniklas if (! seginfo->frchainP)
4752159047fSniklas seginfo->frchainP = frchain_now;
4762159047fSniklas return secptr;
4772159047fSniklas }
4782159047fSniklas
4792159047fSniklas void
subseg_set(segT secptr,subsegT subseg)480*007c2a45Smiod subseg_set (segT secptr, subsegT subseg)
4812159047fSniklas {
4822159047fSniklas if (! (secptr == now_seg && subseg == now_subseg))
4832159047fSniklas subseg_set_rest (secptr, subseg);
4842159047fSniklas mri_common_symbol = NULL;
4852159047fSniklas }
4862159047fSniklas
4872159047fSniklas #ifndef obj_sec_sym_ok_for_reloc
4882159047fSniklas #define obj_sec_sym_ok_for_reloc(SEC) 0
4892159047fSniklas #endif
4902159047fSniklas
4912159047fSniklas /* Get the gas information we are storing for a section. */
4922159047fSniklas
4932159047fSniklas segment_info_type *
seg_info(segT sec)494*007c2a45Smiod seg_info (segT sec)
4952159047fSniklas {
4962159047fSniklas if (sec == bfd_abs_section_ptr)
4972159047fSniklas return abs_seg_info;
4982159047fSniklas else if (sec == bfd_und_section_ptr)
4992159047fSniklas return und_seg_info;
5002159047fSniklas else
5012159047fSniklas return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
5022159047fSniklas }
5032159047fSniklas
5042159047fSniklas symbolS *
section_symbol(segT sec)505*007c2a45Smiod section_symbol (segT sec)
5062159047fSniklas {
5072159047fSniklas segment_info_type *seginfo = seg_info (sec);
5082159047fSniklas symbolS *s;
5092159047fSniklas
5102159047fSniklas if (seginfo == 0)
5112159047fSniklas abort ();
5122159047fSniklas if (seginfo->sym)
5132159047fSniklas return seginfo->sym;
514191aa565Sniklas
5152159047fSniklas #ifndef EMIT_SECTION_SYMBOLS
5162159047fSniklas #define EMIT_SECTION_SYMBOLS 1
5172159047fSniklas #endif
5182159047fSniklas
519c074d1c9Sdrahn if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen)
520b305b0f1Sespie {
5212159047fSniklas /* Here we know it won't be going into the symbol table. */
522c074d1c9Sdrahn s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag);
523b305b0f1Sespie }
5242159047fSniklas else
525b305b0f1Sespie {
526c074d1c9Sdrahn s = symbol_find_base (sec->symbol->name, 0);
527b305b0f1Sespie if (s == NULL)
528c074d1c9Sdrahn s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag);
529b305b0f1Sespie else
530b305b0f1Sespie {
531b305b0f1Sespie if (S_GET_SEGMENT (s) == undefined_section)
532b305b0f1Sespie {
533b305b0f1Sespie S_SET_SEGMENT (s, sec);
534b305b0f1Sespie symbol_set_frag (s, &zero_address_frag);
535b305b0f1Sespie }
536b305b0f1Sespie }
537b305b0f1Sespie }
538b305b0f1Sespie
5392159047fSniklas S_CLEAR_EXTERNAL (s);
5402159047fSniklas
5412159047fSniklas /* Use the BFD section symbol, if possible. */
5422159047fSniklas if (obj_sec_sym_ok_for_reloc (sec))
543b305b0f1Sespie symbol_set_bfdsym (s, sec->symbol);
544c074d1c9Sdrahn else
545c074d1c9Sdrahn symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
546191aa565Sniklas
5472159047fSniklas seginfo->sym = s;
5482159047fSniklas return s;
5492159047fSniklas }
5502159047fSniklas
5512159047fSniklas #endif /* BFD_ASSEMBLER */
5522159047fSniklas
553b305b0f1Sespie /* Return whether the specified segment is thought to hold text. */
554b305b0f1Sespie
555b305b0f1Sespie #ifndef BFD_ASSEMBLER
556b55d4692Sfgsch const char * const nontext_section_names[] = {
557b305b0f1Sespie ".eh_frame",
558b305b0f1Sespie ".gcc_except_table",
559b305b0f1Sespie #ifdef OBJ_COFF
560b305b0f1Sespie #ifndef COFF_LONG_SECTION_NAMES
561b305b0f1Sespie ".eh_fram",
562b305b0f1Sespie ".gcc_exc",
563b305b0f1Sespie #endif
564b305b0f1Sespie #endif
565b305b0f1Sespie NULL
566b305b0f1Sespie };
567b305b0f1Sespie #endif /* ! BFD_ASSEMBLER */
568b305b0f1Sespie
569b305b0f1Sespie int
subseg_text_p(segT sec)570*007c2a45Smiod subseg_text_p (segT sec)
571b305b0f1Sespie {
572b305b0f1Sespie #ifdef BFD_ASSEMBLER
573b305b0f1Sespie return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
574b305b0f1Sespie #else /* ! BFD_ASSEMBLER */
575b305b0f1Sespie const char * const *p;
576b305b0f1Sespie
577c074d1c9Sdrahn if (sec == data_section || sec == bss_section || sec == absolute_section)
578b305b0f1Sespie return 0;
579b305b0f1Sespie
580b305b0f1Sespie for (p = nontext_section_names; *p != NULL; ++p)
581b305b0f1Sespie {
582b305b0f1Sespie if (strcmp (segment_name (sec), *p) == 0)
583b305b0f1Sespie return 0;
584b305b0f1Sespie
585b305b0f1Sespie #ifdef obj_segment_name
586b305b0f1Sespie if (strcmp (obj_segment_name (sec), *p) == 0)
587b305b0f1Sespie return 0;
588b305b0f1Sespie #endif
589b305b0f1Sespie }
590b305b0f1Sespie
591b305b0f1Sespie return 1;
592b305b0f1Sespie
593b305b0f1Sespie #endif /* ! BFD_ASSEMBLER */
594b305b0f1Sespie }
595b305b0f1Sespie
596191aa565Sniklas void
subsegs_print_statistics(FILE * file)597*007c2a45Smiod subsegs_print_statistics (FILE *file)
598191aa565Sniklas {
599191aa565Sniklas frchainS *frchp;
600191aa565Sniklas fprintf (file, "frag chains:\n");
601191aa565Sniklas for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
602191aa565Sniklas {
603191aa565Sniklas int count = 0;
604191aa565Sniklas fragS *fragp;
605191aa565Sniklas
606191aa565Sniklas /* If frch_subseg is non-zero, it's probably been chained onto
607191aa565Sniklas the end of a previous subsection. Don't count it again. */
608191aa565Sniklas if (frchp->frch_subseg != 0)
609191aa565Sniklas continue;
610191aa565Sniklas
611191aa565Sniklas /* Skip gas-internal sections. */
612191aa565Sniklas if (segment_name (frchp->frch_seg)[0] == '*')
613191aa565Sniklas continue;
614191aa565Sniklas
615191aa565Sniklas for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
616191aa565Sniklas {
617191aa565Sniklas #if 0
618191aa565Sniklas switch (fragp->fr_type)
619191aa565Sniklas {
620191aa565Sniklas case rs_fill:
621191aa565Sniklas fprintf (file, "f"); break;
622191aa565Sniklas case rs_align:
623191aa565Sniklas fprintf (file, "a"); break;
624191aa565Sniklas case rs_align_code:
625191aa565Sniklas fprintf (file, "c"); break;
626191aa565Sniklas case rs_org:
627191aa565Sniklas fprintf (file, "o"); break;
628191aa565Sniklas case rs_machine_dependent:
629191aa565Sniklas fprintf (file, "m"); break;
630191aa565Sniklas case rs_space:
631191aa565Sniklas fprintf (file, "s"); break;
632191aa565Sniklas case 0:
633191aa565Sniklas fprintf (file, "0"); break;
634191aa565Sniklas default:
635191aa565Sniklas fprintf (file, "?"); break;
636191aa565Sniklas }
637191aa565Sniklas #endif
638191aa565Sniklas count++;
639191aa565Sniklas }
640191aa565Sniklas fprintf (file, "\n");
641c074d1c9Sdrahn fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
642191aa565Sniklas segment_name (frchp->frch_seg), count);
643191aa565Sniklas }
644191aa565Sniklas }
645191aa565Sniklas
6462159047fSniklas /* end of subsegs.c */
647