This is sections.c in view mode; [Download] [Up]
/* sections.c (was subsegs.c in original GAS version) Copyright (C) 1987 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Mach-O sections are chains of fragments. */ #include <stdlib.h> #include <strings.h> #include "sections.h" #include "obstack.h" #include "xmalloc.h" #include "frags.h" #include "messages.h" /* * All sections' chains hang off here. NULL means no frchains yet. */ frchainS *frchain_root = NULL; /* * The frchain we are assembling into now. That is, the current section's * frag chain, even if it contains no (complete) frags. */ frchainS *frchain_now = NULL; /* * sections_begin() sets up to allow sections to be created. */ void sections_begin( void) { /* This may be needed if a section_new() for .text is not assumed */ /* obstack_begin(&frags, 5000); */ /* frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); */ } /* * section_new() (for non-zerofill sections) switches to a new section, creating * it if needed, and creates a fresh fragment. If it is the current section * nothing happens except checks to make sure the type, attributes and * sizeof_stub are the same. The segment and section names will be trimed to * fit in the section structure and is the responsiblity of the caller to * report errors if they don't. For zerofill sections only the struct frchain * for the section is returned after possibly being created (these section are * never made the current section and no frags are ever touched). * * Globals on input: * frchain_now points to the (possibly none) struct frchain for the current * section. * frag_now points at an incomplete frag for current section. * If frag_now == NULL, then there is no old, incomplete frag, so the old * frag is not closed off. * * Globals on output: * frchain_now points to the (possibly new) struct frchain for this section. * frchain_root updated if needed (for the first section created). * frag_now is set to the last (possibly new) frag in the section. */ frchainS * section_new( char *segname, char *sectname, unsigned long type, unsigned long attributes, unsigned long sizeof_stub) { frchainS *frcP; frchainS **lastPP; unsigned long last_nsect; if(frags.chunk_size == 0) /* * This line is use instead of: * obstack_begin(&frags, 5000); * which the only difference is that frags are allocated on 4 byte * boundaries instead of the default. The problem with the default * is that on some RISC machines the obstack uses 8 (the alignment * of a double after a char in a struct) and then the common use of: * frag_now->fr_fix = obstack_next_free(&frags) - * frag_now->fr_literal; * can get an extra 4 bytes that are not in the frag because of the * 8 byte alignment where only 4 byte alignment for frags are * needed. */ _obstack_begin(&frags, 5000, 4, obstack_chunk_alloc, obstack_chunk_free); /* * Determine if this section has been seen. */ last_nsect = 0; for(frcP = *(lastPP = &frchain_root); frcP != NULL; frcP = *(lastPP = &frcP->frch_next)){ if(strncmp(frcP->frch_section.segname, segname, sizeof(frcP->frch_section.segname)) == 0 && strncmp(frcP->frch_section.sectname, sectname, sizeof(frcP->frch_section.sectname)) == 0) break; last_nsect = frcP->frch_nsect; } /* * If this section has been seen make sure it's type and attributes * for this call are the same as when the section was created. */ if(frcP != NULL){ if((frcP->frch_section.flags & SECTION_TYPE) != type){ as_warn("section type does not match previous section type"); } if(type == S_SYMBOL_STUBS && frcP->frch_section.reserved2 != sizeof_stub){ as_warn("section stub size does not match previous section " "stub size"); } if((frcP->frch_section.flags & SECTION_ATTRIBUTES) != attributes){ as_warn("section attributes does not match previous section " "attributes"); } } /* * If the current section is the same as for this call there is nothing * more to do. */ if(frcP != NULL && (frchain_now == frcP || type == S_ZEROFILL)){ return(frcP); } /* * For non-zerofill sections it will be made the current section so deal * with the current frag. */ if(type != S_ZEROFILL){ /* * If there is any current frag in the old section close it off. */ if(frag_now != NULL){ frag_now->fr_fix = obstack_next_free(&frags) - frag_now->fr_literal; frag_wane(frag_now); } /* * We must do the obstack_finish(), so the next object we put on * obstack frags will not appear to start at the fr_literal of the * current frag. Also, it ensures that the next object will begin * on a address that is aligned correctly for the engine that runs * the assembler. */ obstack_finish(&frags); } /* * If this section exists since it is not the current section switch to * it by making it the current chain and create a new frag in it. */ if(frcP != NULL){ /* * For a zerofill section no frags are created here and since it * exist just return a pointer to the section. */ if((frcP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL){ return(frcP); } else{ /* * Make this section the current section. */ frchain_now = frcP; /* * Make a fresh frag for the section. */ frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; /* * Append the new frag to the existing frchain. */ frchain_now->frch_last->fr_next = frag_now; frchain_now->frch_last = frag_now; } } else{ /* * This section does not exist so create a new frchainS struct fill * it in, link it to the chain */ frcP = (frchainS *)xmalloc(sizeof(frchainS)); memset(frcP, '\0', sizeof(frchainS)); strncpy(frcP->frch_section.segname, segname, sizeof(frcP->frch_section.segname)); strncpy(frcP->frch_section.sectname, sectname, sizeof(frcP->frch_section.sectname)); frcP->frch_section.flags = attributes | type; frcP->frch_section.reserved2 = sizeof_stub; frcP->frch_nsect = last_nsect + 1; *lastPP = frcP; /* * For zerofill sections no frag is created here so just return. * For non-zerofill section create the sections new frag and * make the section the current chain. */ if(type == S_ZEROFILL){ return(frcP); } else{ /* * Make a fresh frag for the new section. */ frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; /* * Append the new frag to new frchain. */ frcP->frch_root = frag_now; frcP->frch_last = frag_now; /* * Make this section the current section. */ frchain_now = frcP; } } return(frchain_now); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.