Initial revision
authorSteve Chamberlain <steve@cygnus>
Thu, 4 Jul 1991 16:52:19 +0000 (16:52 +0000)
committerSteve Chamberlain <steve@cygnus>
Thu, 4 Jul 1991 16:52:19 +0000 (16:52 +0000)
bfd/core.c [new file with mode: 0644]
bfd/reloc.c [new file with mode: 0644]
bfd/section.c [new file with mode: 0644]

diff --git a/bfd/core.c b/bfd/core.c
new file mode 100644 (file)
index 0000000..b4ab497
--- /dev/null
@@ -0,0 +1,65 @@
+/*doc*
+@section Core files
+Buff output this facinating topic
+*/
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+/** Some core file info commands */
+
+/*proto*i bfd_core_file_failing_command
+Returns a read-only string explaining what program was running when
+it failed and produced the core file being read
+
+*; PROTO(CONST char *, bfd_core_file_failing_command, (bfd *));
+*/
+
+CONST char *
+DEFUN(bfd_core_file_failing_command,(abfd),
+      bfd *abfd)
+{
+  if (abfd->format != bfd_core) {
+    bfd_error = invalid_operation;
+    return NULL;
+  }
+  return BFD_SEND (abfd, _core_file_failing_command, (abfd));
+}
+
+/*proto* bfd_core_file_failing_signal
+Returns the signal number which caused the core dump which generated
+the file the bfd is attatched to.
+
+*; PROTO(int, bfd_core_file_failing_signal, (bfd *));
+*/
+int
+bfd_core_file_failing_signal (abfd)
+     bfd *abfd;
+{
+  if (abfd->format != bfd_core) {
+    bfd_error = invalid_operation;
+    return 0;
+  }
+  return BFD_SEND (abfd, _core_file_failing_signal, (abfd));
+}
+
+
+/*proto* core_file_matches_executable_p
+Returns @code{true} if the core file attatched to @var{core_bfd} was
+generated by a run of the executable file attatched to @var{exec_bfd},
+or else @code{false}.
+*; PROTO(boolean, core_file_matches_executable_p,
+    (bfd *core_bfd, bfd *exec_bfd));
+*/
+boolean
+core_file_matches_executable_p (core_bfd, exec_bfd)
+     bfd *core_bfd, *exec_bfd;
+{
+  if ((core_bfd->format != bfd_core) || (exec_bfd->format != bfd_object)) {
+    bfd_error = wrong_format;
+    return false;
+  }
+
+  return BFD_SEND (core_bfd, _core_file_matches_executable_p, (core_bfd, exec_bfd));
+}
diff --git a/bfd/reloc.c b/bfd/reloc.c
new file mode 100644 (file)
index 0000000..2d1f6a5
--- /dev/null
@@ -0,0 +1,612 @@
+/*doc*
+@section Relocations
+
+Bfd maintains relocations in much the same was as it maintains
+symbols; they are left alone until required, then read in en-mass and
+traslated into an internal form. There is a common routine
+@code{bfd_perform_relocation} which acts upon the canonical form to to
+the actual fixup.
+
+Note that relocations are maintained on a per section basis, whilst
+symbols are maintained on a per bfd basis.
+
+All a back end has to do to fit the bfd interface is to create as many
+@code{struct reloc_cache_entry} as there are relocations in a
+particuar section, and fill in the right bits:
+
+@menu
+* typedef arelent::
+* reloc handling functions::
+@end menu
+
+*/
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+/*doc
+*node typedef arelent, Relocations, reloc handling functions, Relocations
+@section typedef arelent
+
+
+*/
+
+/*proto* bfd_perform_relocation
+The relocation routine returns as a status an enumerated type:
+
+*+++
+
+$typedef enum bfd_reloc_status {
+No errors detected
+
+$  bfd_reloc_ok,
+
+The relocation was performed, but there was an overflow.
+
+$  bfd_reloc_overflow,
+
+The address to relocate was not within the section supplied
+
+$  bfd_reloc_outofrange,
+
+Used by special functions
+
+$  bfd_reloc_continue,
+
+Unused 
+
+$  bfd_reloc_notsupported,
+
+Unsupported relocation size requested. 
+
+$  bfd_reloc_other,
+
+The symbol to relocate against was undefined.
+
+$  bfd_reloc_undefined,
+
+The relocaction was performed, but may not be ok - presently generated
+only when linking i960 coff files with i960 b.out symbols.
+
+$  bfd_reloc_dangerous
+$   }
+$ bfd_reloc_status_enum_type;
+
+*---
+
+*/
+
+/*proto*
+
+*+++
+
+$typedef struct reloc_cache_entry 
+${
+
+A pointer into the canonical table of pointers 
+
+$  struct symbol_cache_entry **sym_ptr_ptr;
+
+offset in section                 
+
+$  rawdata_offset address;
+
+addend for relocation value        
+
+$  bfd_vma addend;    
+
+if sym is null this is the section 
+
+$  struct sec *section;
+
+Pointer to how to perform the required relocation
+
+$  struct reloc_howto_struct *howto;
+$} arelent;
+
+*---
+
+*/
+
+/*doc*
+@table @code
+@item sym_ptr_ptr
+The symbol table pointer points to a pointer to the symbol ascociated with the
+relocation request. This would naturaly be the pointer into the table
+returned by the back end's get_symtab action. @xref{Symbols}. The
+symbol is referenced through a pointer to a pointer so that tools like
+the linker can fixup all the symbols of the same name by modifying
+only one pointer. The relocation routine looks in the symbol and uses
+the base of the section the symbol is attatched to and the value of
+the symbol as the initial relocation offset. If the symbol pointer is
+zero, then the section provided is looked up.
+@item address
+The address field gives the offset in bytes from the base of the
+section data which owns the relocation record to the first byte of
+relocatable information. The actual data relocated will be relative to
+this point - for example, a relocation type which modifies the bottom
+two bytes of a four byte word would not touch the first byte pointed
+to in a big endian world.
+@item addend
+The addend is a value provided by the back end to be added (!) to the
+relocation offset. It's interpretation is dependent upon the howto.
+For example, on the 68k the code:
+
+*+
+        char foo[];
+        main()
+                {
+                return foo[0x12345678];
+                }
+*-
+Could be compiled into:
+
+*+
+        linkw fp,#-4
+        moveb @@#12345678,d0
+        extbl d0
+        unlk fp
+        rts
+*-
+
+This could create a reloc pointing to foo, but leave the offset in the data
+(something like)
+
+*+
+RELOCATION RECORDS FOR [.text]:
+OFFSET   TYPE      VALUE 
+00000006 32        _foo
+
+00000000 4e56 fffc          ; linkw fp,#-4
+00000004 1039 1234 5678     ; moveb @@#12345678,d0
+0000000a 49c0               ; extbl d0
+0000000c 4e5e               ; unlk fp
+0000000e 4e75               ; rts
+*-
+Using coff and an 88k, some instructions don't have enough space in them to
+represent the full address range, and pointers have to be loaded in
+two parts. So you'd get something like:
+
+*+
+        or.u     r13,r0,hi16(_foo+0x12345678)
+        ld.b     r2,r13,lo16(_foo+0x12345678)
+        jmp      r1
+*-
+This whould create two relocs, both pointing to _foo, and with 0x12340000
+in their addend field. The data would consist of:
+
+*+
+
+RELOCATION RECORDS FOR [.text]:
+OFFSET   TYPE      VALUE 
+00000002 HVRT16    _foo+0x12340000
+00000006 LVRT16    _foo+0x12340000
+
+00000000 5da05678           ; or.u r13,r0,0x5678
+00000004 1c4d5678           ; ld.b r2,r13,0x5678
+00000008 f400c001           ; jmp r1
+*-
+The relocation routine digs out the value from the data, adds it to
+the addend to get the original offset and then adds the value of _foo.
+Note that all 32 bits have to be kept around somewhere, to cope with
+carry from bit 15 to bit 16.
+
+On further example is the sparc and the a.out format. The sparc has a
+similar problem to the 88k, in that some instructions don't have
+room for an entire offset, but on the sparc the parts are created odd
+sized lumps. The designers of the a.out format chose not to use the
+data within the section for storing part of the offset; all the offset
+is kept within the reloc. Any thing in the data should be ignored.
+
+*+
+        save %sp,-112,%sp
+        sethi %hi(_foo+0x12345678),%g2
+        ldsb [%g2+%lo(_foo+0x12345678)],%i0
+        ret
+        restore
+*-
+Both relocs contains a pointer to foo, and the offsets would contain junk.
+
+*+
+RELOCATION RECORDS FOR [.text]:
+OFFSET   TYPE      VALUE 
+00000004 HI22      _foo+0x12345678
+00000008 LO10      _foo+0x12345678
+
+00000000 9de3bf90     ; save %sp,-112,%sp
+00000004 05000000     ; sethi %hi(_foo+0),%g2
+00000008 f048a000     ; ldsb [%g2+%lo(_foo+0)],%i0
+0000000c 81c7e008     ; ret
+00000010 81e80000     ; restore
+*-
+@item section  
+The section field is only used when the symbol pointer field is null.
+It supplies the section into which the data should be relocated. The
+field's main use comes from assemblers which do most of the symbol fixups
+themselves; an assembler may take an internal reference to a label,
+but since it knows where the label is, it can turn the relocation
+request from a symbol lookup into a section relative relocation - the
+relocation emitted has no symbol, just a section to relocate against.
+
+I'm not sure what it means when both a symbol pointer an a section
+pointer are present. Some formats use this sort of mechanism to
+describe PIC relocations, but bfd can't to that sort of thing yet.
+@item howto
+The howto field can be imagined as a relocation instruction. It is a
+pointer to a struct which contains information on what to do with all
+the other information in the reloc record and data section. A back end
+would normally have a relocation instruction set and turn relocations
+into pointers to the correct structure on input - but it would be
+possible to create each howto field on demand.
+@end table
+*/
+
+
+/*proto* reloc_howto_type
+The @code{reloc_howto_type} is a structure which contains all the
+information that bfd needs to know to tie up a back end's data.
+
+*+++
+
+$typedef CONST struct reloc_howto_struct 
+${ 
+The type field has mainly a documetary use - the back end can to what
+it wants with it, though the normally the back end's external idea of
+what a reloc number would be would be stored in this field. For
+example, the a PC relative word relocation in a coff environment would
+have the type 023 - because that's what the outside world calls a
+R_PCRWORD reloc.
+
+$  unsigned int type;
+
+The value the final relocation is shifted right by. This drops
+unwanted data from the relocation. 
+
+$  unsigned int rightshift;
+
+The size of the item to be relocated - 0, is one byte, 1 is 2 bytes, 3
+is four bytes.
+
+$  unsigned int size;
+
+Now obsolete
+
+$  unsigned int bitsize;
+
+Notes that the relocation is relative to the location in the data
+section of the addend. The relocation function will subtract from the
+relocation value the address of the location being relocated.
+
+$  boolean pc_relative;
+
+Now obsolete
+
+$  unsigned int bitpos;
+
+Now obsolete
+
+$  boolean absolute;
+
+Causes the relocation routine to return an error if overflow is
+detected when relocating.
+
+$  boolean complain_on_overflow;
+
+If this field is non null, then the supplied function is called rather
+than the normal function. This allows really strange relocation
+methods to be accomodated (eg, i960 callj instructions).
+
+$  bfd_reloc_status_enum_type (*special_function)();
+
+The textual name of the relocation type.
+
+$  char *name;
+
+When performing a partial link, some formats must modify the
+relocations rather than the data - this flag signals this.
+
+$  boolean partial_inplace;
+
+The src_mask is used to select what parts of the read in data are to
+be used in the relocation sum. Eg, if this was an 8 bit bit of data
+which we read and relocated, this would be 0x000000ff. When we have
+relocs which have an addend, such as sun4 extended relocs, the value
+in the offset part of a relocating field is garbage so we never use
+it. In this case the mask would be 0x00000000.
+
+$  bfd_word src_mask;
+The dst_mask is what parts of the instruction are replaced into the
+instruction. In most cases src_mask == dst_mask, except in the above
+special case, where dst_mask would be 0x000000ff, and src_mask would
+be 0x00000000.
+
+$  bfd_word dst_mask;           
+
+When some formats create PC relative instructions, they leave the
+value of the pc of the place being relocated in the offset slot of the
+instruction, so that a PC relative relocation can be made just by
+adding in an ordinary offset (eg sun3 a.out). Some formats leave the
+displacement part of an instruction empty (eg m88k bcs), this flag
+signals the fact.
+
+$  boolean pcrel_offset;
+$} reloc_howto_type;
+*---
+
+*/
+
+/*proto* HOWTO
+The HOWTO define is horrible and will go away.
+*+
+#define HOWTO(C, R,S,B, P, BI, ABS, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+  {(unsigned)C,R,S,B, P, BI, ABS,O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC}
+*-
+
+*/
+
+/*proto* reloc_chain
+*+
+typedef unsigned char bfd_byte;
+
+typedef struct relent_chain {
+  arelent relent;
+  struct   relent_chain *next;
+} arelent_chain;
+
+*-
+
+*/
+
+
+
+/*proto*
+If an output_bfd is supplied to this function the generated image
+will be relocatable, the relocations are copied to the output file
+after they have been changed to reflect the new state of the world.
+There are two ways of reflecting the results of partial linkage in an
+output file; by modifying the output data in place, and by modifying
+the relocation record. Some native formats (eg basic a.out and basic
+coff) have no way of specifying an addend in the relocation type, so
+the addend has to go in the output data.  This is no big deal since in
+these formats the output data slot will always be big enough for the
+addend. Complex reloc types with addends were invented to solve just
+this problem.
+*; PROTO(bfd_reloc_status_enum_type,
+                bfd_perform_relocation,
+                        (bfd * abfd,
+                        arelent *reloc_entry,
+                        PTR data,
+                        asection *input_section,
+                        bfd *output_bfd));
+*/
+
+
+bfd_reloc_status_enum_type
+DEFUN(bfd_perform_relocation,(abfd,
+                              reloc_entry,
+                              data,
+                              input_section,
+                              output_bfd),
+      bfd *abfd AND
+      arelent *reloc_entry AND
+      PTR data AND
+      asection *input_section AND
+      bfd *output_bfd)
+{
+  bfd_vma relocation;
+  bfd_reloc_status_enum_type flag = bfd_reloc_ok;
+  bfd_vma addr = reloc_entry->address ;
+  bfd_vma output_base = 0;
+  reloc_howto_type *howto = reloc_entry->howto;
+  asection *reloc_target_output_section;
+  asection *reloc_target_input_section;
+  asymbol *symbol;
+
+  if (reloc_entry->sym_ptr_ptr) {
+    symbol = *( reloc_entry->sym_ptr_ptr);
+    if ((symbol->flags & BSF_UNDEFINED) && output_bfd == (bfd *)NULL) {
+      flag = bfd_reloc_undefined;
+    }
+  }
+  else {
+    symbol = (asymbol*)NULL;
+  }
+
+  if (howto->special_function){
+    bfd_reloc_status_enum_type cont;
+    cont = howto->special_function(abfd,
+                                   reloc_entry,
+                                   symbol,
+                                   data,
+                                   input_section);
+    if (cont != bfd_reloc_continue) return cont;
+  }
+
+  /* 
+    Work out which section the relocation is targetted at and the
+    initial relocation command value.
+    */
+
+
+  if (symbol != (asymbol *)NULL){
+    if (symbol->flags & BSF_FORT_COMM) {
+      relocation = 0;
+    }
+    else {
+      relocation = symbol->value;
+    }
+    if (symbol->section != (asection *)NULL)
+        {
+          reloc_target_input_section = symbol->section;
+        }
+    else {
+      reloc_target_input_section = (asection *)NULL;
+    }
+  }
+  else if (reloc_entry->section != (asection *)NULL)
+      {
+        relocation = 0;
+        reloc_target_input_section = reloc_entry->section;
+      }
+  else {
+    relocation = 0;
+    reloc_target_input_section = (asection *)NULL;
+  }
+
+
+  if (reloc_target_input_section != (asection *)NULL) {
+
+    reloc_target_output_section =
+      reloc_target_input_section->output_section;
+
+    if (output_bfd && howto->partial_inplace==false) {
+      output_base = 0;
+    }
+    else {
+      output_base = reloc_target_output_section->vma;
+
+    }
+
+    relocation += output_base +   reloc_target_input_section->output_offset;
+  }
+
+  relocation += reloc_entry->addend ;
+
+
+  if(reloc_entry->address > (bfd_vma)(input_section->size)) 
+      {
+        return bfd_reloc_outofrange;
+      }
+          
+
+  if (howto->pc_relative == true)
+      {
+        /*
+          Anything which started out as pc relative should end up that
+          way too. 
+
+          There are two ways we can see a pcrel instruction. Sometimes
+          the pcrel displacement has been partially calculated, it
+          includes the distance from the start of the section to the
+          instruction in it (eg sun3), and sometimes the field is
+          totally blank - eg m88kbcs.
+          */
+
+        
+        relocation -= 
+          output_base +   input_section->output_offset;
+
+        if (howto->pcrel_offset == true) {
+          relocation -= reloc_entry->address;
+        }
+
+      }
+
+  if (output_bfd!= (bfd *)NULL) {
+    if ( howto->partial_inplace == false)  {
+      /*
+        This is a partial relocation, and we want to apply the relocation
+        to the reloc entry rather than the raw data. Modify the reloc
+        inplace to reflect what we now know.
+        */
+      reloc_entry->addend = relocation  ;
+      reloc_entry->section = reloc_target_input_section;
+      if (reloc_target_input_section != (asection *)NULL) {
+        /* If we know the output section we can forget the symbol */
+        reloc_entry->sym_ptr_ptr = (asymbol**)NULL;
+      }
+      reloc_entry->address += 
+        input_section->output_offset;
+      return flag;
+    }
+    else 
+        {
+          /* This is a partial relocation, but inplace, so modify the
+             reloc record a bit
+             */
+
+        }
+  }
+
+  reloc_entry->addend = 0;
+
+
+  /* 
+    Either we are relocating all the way, or we don't want to apply
+    the relocation to the reloc entry (probably because there isn't
+    any room in the output format to describe addends to relocs)
+    */
+  relocation >>= howto->rightshift;
+
+  /* Shift everything up to where it's going to be used */
+   
+  relocation <<= howto->bitpos;
+
+  /* Wait for the day when all have the mask in them */
+
+  /* What we do:
+     i instruction to be left alone
+     o offset within instruction
+     r relocation offset to apply
+     S src mask
+     D dst mask
+     N ~dst mask
+     A part 1
+     B part 2
+     R result
+     
+     Do this:
+     i i i i i o o o o o        from bfd_get<size>
+     and           S S S S S    to get the size offset we want
+     +   r r r r r r r r r r  to get the final value to place
+     and           D D D D D  to chop to right size
+     -----------------------
+     A A A A A 
+     And this:
+     ...   i i i i i o o o o o  from bfd_get<size>
+     and   N N N N N            get instruction
+     -----------------------
+     ...   B B B B B
+     
+     And then:       
+     B B B B B       
+     or              A A A A A     
+     -----------------------
+     R R R R R R R R R R        put into bfd_put<size>
+     */
+
+#define DOIT(x) \
+  x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) +  relocation) & howto->dst_mask))
+
+    switch (howto->size)
+        {
+        case 0:
+            {
+              char x = bfd_get_8(abfd, (char *)data + addr);
+              DOIT(x);
+              bfd_put_8(abfd,x, (unsigned char *) data + addr);
+            }
+          break;
+
+        case 1:
+            { 
+              short x = bfd_get_16(abfd, (bfd_byte *)data + addr);
+              DOIT(x);
+              bfd_put_16(abfd, x,   (unsigned char *)data + addr);
+            }
+          break;
+        case 2:
+            {
+              long  x = bfd_get_32(abfd, (bfd_byte *) data + addr);
+              DOIT(x);
+              bfd_put_32(abfd,x,    (bfd_byte *)data + addr);
+            }      
+          break;
+        case 3:
+          /* Do nothing */
+          break;
+        default:
+          return bfd_reloc_other;
+        }
+
+  return flag;
+}
diff --git a/bfd/section.c b/bfd/section.c
new file mode 100644 (file)
index 0000000..099f0bd
--- /dev/null
@@ -0,0 +1,553 @@
+/*doc*
+@section Sections
+Sections are supported in bfd in @code{section.c}.
+
+The raw data contained within a bfd is maintained through the section
+abstraction.  A single bfd may have any number of sections, and keeps
+hold of them by pointing to the first, each one points to the next in
+the list.
+
+@menu
+* Section Input::
+* Section Output::
+* typedef asection::
+* section prototypes::
+@end menu
+
+@node Section Input, Section Output,,Sections
+@comment  node-name,  next,  previous,  up
+@subsection Section Input
+When a bfd is opened for reading, the section structures are created
+and attatched to the bfd.
+
+Each section has a name which describes the section in the outside
+world - for example, @code{a.out} would contain at least three
+sections, called @code{.text}, @code{.data} and @code{.bss}. 
+
+Sometimes a bfd will contain more than the 'natural' number of
+sections. A back end may attatch other sections containing constructor
+data, or an application may add a section (using bfd_make_section) to
+the sections attatched to an already open bfd. For example, the linker
+creates a supernumary section @code{COMMON} for each input file's bfd
+to hold information about common storage.
+
+The raw data is not necessarily read in at the same time as the
+section descriptor is created. Some targets may leave the data in
+place until a @code{bfd_get_section_contents} call is made. Other back
+ends may read in all the data at once - For example; an S-record file
+has to be read once to determine the size of the data. An IEEE-695
+file doesn't contain raw data in sections, but data and relocation
+expressions intermixed, so the data area has to be parsed to get out
+the data and relocations.
+
+@node Section Output,typedef asection,Section Input,Sections
+@subsection Section Output
+To write a new object style bfd, the various sections to be written
+have to be created. They are attatched to the bfd in the same way as
+input sections, data is written to the sections using
+@code{bfd_set_section_contents}. 
+
+The linker uses the fields @code{output_section} and
+@code{output_offset} to create an output file.
+
+The data to be written comes from input sections attatched to the
+output sections.  The output section structure can be considered a
+filter for the input section, the output section determines the vma of
+the output data and the name, but the input section determines the
+offset into the output section of the data to be written.
+
+Eg to create a section "O", starting at 0x100, 0x123 long, containing two
+subsections, "A" at offset 0x0 (ie at vma 0x100) and "B" at offset
+0x20 (ie at vma 0x120) the structures would look like:
+
+*+
+
+   section name          "A"
+     output_offset   0x00
+     size            0x20
+     output_section ----------->  section name    "O"
+                             |    vma             0x100
+   section name          "B" |    size            0x123
+     output_offset   0x20    |
+     size            0x103   |
+     output_section  --------|
+
+*-
+
+*/
+
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+
+/*doc*
+@node typedef asection,section prototypes,Section Output,Sections
+@subsection typedef asection
+*/
+
+/*proto*
+The shape of a section struct:
+
+*+++
+
+$typedef struct sec {
+
+The name of the section, the name isn't a copy, the pointer is
+the same as that passed to bfd_make_section.
+
+$    CONST char *name;
+
+The next section in the list belonging to the bfd, or NULL.
+
+$    struct sec *next;
+
+The field flags contains attributes of the section. Some of these
+flags are read in from the object file, and some are synthesized from
+other information. 
+
+$flagword flags;
+
+
+$#define SEC_NO_FLAGS   0x000
+
+Tells the OS to allocate space for this section when loaded.
+This would clear for a section containing debug information only.
+
+$#define SEC_ALLOC      0x001
+
+Tells the OS to load the section from the file when loading.
+This would be clear for a .bss section 
+
+$#define SEC_LOAD       0x002
+
+The section contains data still to be relocated, so there will be some
+relocation information too.
+
+$#define SEC_RELOC      0x004
+
+Obsolete ? 
+
+$#define SEC_BALIGN     0x008
+
+A signal to the OS that the section contains read only data.
+
+$#define SEC_READONLY   0x010
+
+The section contains code only.
+
+$#define SEC_CODE       0x020
+
+The section contains data only.
+
+$#define SEC_DATA        0x040
+
+The section will reside in ROM.
+
+$#define SEC_ROM        0x080
+
+The section contains constructor information. This section type is
+used by the linker to create lists of constructors and destructors
+used by @code{g++}. When a back end sees a symbol which should be used
+in a constructor list, it creates a new section for the type of name
+(eg @code{__CTOR_LIST__}), attatches the symbol to it and builds a
+relocation. To build the lists of constructors, all the linker has to
+to is catenate all the sections called @code{__CTOR_LIST__} and
+relocte the data contained within - exactly the operations it would
+peform on standard data.
+
+$#define SEC_CONSTRUCTOR 0x100
+
+The section has contents - a bss section could be
+@code{SEC_ALLOC} | @code{SEC_HAS_CONTENTS}, a debug section could be
+@code{SEC_HAS_CONTENTS}
+
+$#define SEC_HAS_CONTENTS 0x200
+
+An instruction to the linker not to output sections containing
+this flag even if they have information which would normally be written.
+
+$#define SEC_NEVER_LOAD 0x400
+
+The base address of the section in the address space of the target.
+
+$   bfd_vma vma;
+
+The size of the section in bytes of the loaded section. This contains
+a value even if the section has no contents (eg, the size of @code{.bss}).
+
+$   bfd_size_type size;    
+
+If this section is going to be output, then this value is the
+offset into the output section of the first byte in the input
+section. Eg, if this was going to start at the 100th byte in the
+output section, this value would be 100. 
+
+$   bfd_vma output_offset;
+
+The output section through which to map on output.
+
+$   struct sec *output_section;
+
+The alignment requirement of the section, as an exponent - eg 3
+aligns to 2^3 (or 8) 
+
+$   unsigned int alignment_power;
+
+If an input section, a pointer to a vector of relocation records for
+the data in this section.
+
+$   struct reloc_cache_entry *relocation;
+
+If an output section, a pointer to a vector of pointers to
+relocation records for the data in this section.
+
+$   struct reloc_cache_entry **orelocation;
+
+The number of relocation records in one of the above 
+
+$   unsigned reloc_count;
+
+Which section is it 0..nth     
+
+$   int index;                      
+
+Information below is back end specific - and not always used or
+updated 
+
+File position of section data   
+
+$   file_ptr filepos;      
+File position of relocation info        
+
+$   file_ptr rel_filepos;
+
+File position of line data              
+
+$   file_ptr line_filepos;
+
+Pointer to data for applications        
+
+$   PTR userdata;
+
+$   struct lang_output_section *otheruserdata;
+
+Attached line number information        
+
+$   alent *lineno;
+Number of line number records   
+
+$   unsigned int lineno_count;
+
+When a section is being output, this value changes as more
+linenumbers are written out 
+
+$   file_ptr moving_line_filepos;
+
+what the section number is in the target world 
+
+$   unsigned int target_index;
+
+$   PTR used_by_bfd;
+
+If this is a constructor section then here is a list of the
+relocations created to relocate items within it.
+
+$   struct relent_chain *constructor_chain;
+
+The bfd which owns the section.
+
+$   bfd *owner;
+
+$} asection ;
+
+*---
+
+*/
+
+/*doc*
+@node section prototypes,Section,typedef section,Sections
+@subsection section prototypes
+
+*/
+/*proto* bfd_get_section_by_name
+Runs through the provided @var{abfd} and returns the @code{asection}
+who's name matches that provided, otherwise NULL. @xref{Sections}, for more information.
+
+*; PROTO(asection *, bfd_get_section_by_name,
+    (bfd *abfd, CONST char *name));
+*/
+asection *
+DEFUN(bfd_get_section_by_name,(abfd, name),
+      bfd *abfd AND
+      CONST char *name)
+{
+  asection *sect;
+
+  for (sect = abfd->sections; sect != NULL; sect = sect->next)
+    if (!strcmp (sect->name, name)) return sect;
+  return NULL;
+}
+
+
+/*proto* bfd_make_section
+This function creates a new empty section called @var{name} and attatches it
+to the end of the chain of sections for @var{bfd}. An attempt to
+create a section with a name which is already in use, returns the old
+section by that name instead.
+
+Possible errors are:
+@table @code
+@item invalid_operation
+If output has already started for this bfd.
+@item no_memory
+If obstack alloc fails.
+@end table
+
+*; PROTO(asection *, bfd_make_section, (bfd *, CONST char *name));
+*/
+
+
+
+sec_ptr
+DEFUN(bfd_make_section,(abfd, name),
+      bfd *abfd AND
+      CONST char * name)
+{
+  asection *newsect;  
+  asection **  prev = &abfd->sections;
+  asection * sect = abfd->sections;
+  
+  if (abfd->output_has_begun) {
+    bfd_error = invalid_operation;
+    return NULL;
+  }
+
+  while (sect) {
+    if (!strcmp(sect->name, name)) return sect;
+    prev = &sect->next;
+    sect = sect->next;
+  }
+
+  newsect = (asection *) bfd_zalloc(abfd, sizeof (asection));
+  if (newsect == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+
+  newsect->name = name;
+  newsect->index = abfd->section_count++;
+  newsect->flags = SEC_NO_FLAGS;
+
+  newsect->userdata = 0;
+  newsect->next = (asection *)NULL;
+  newsect->relocation = (arelent *)NULL;
+  newsect->reloc_count = 0;
+  newsect->line_filepos =0;
+  newsect->owner = abfd;
+  if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) {
+    free (newsect);
+    return NULL;
+  }
+
+  *prev = newsect;
+  return newsect;
+}
+
+
+/*proto* bfd_set_section_flags
+Attempts to set the attributes of the section named in the bfd
+supplied to the value. Returns true on success, false on error.
+Possible error returns are:
+@table @code
+@item invalid operation
+The section cannot have one or more of the attributes requested. For
+example, a .bss section in @code{a.out} may not have the
+@code{SEC_HAS_CONTENTS} field set.
+@end table
+
+*; PROTO(boolean, bfd_set_section_flags,
+       (bfd *, asection *, flagword));
+*/
+
+boolean
+DEFUN(bfd_set_section_flags,(abfd, section, flags),
+     bfd *abfd AND
+     sec_ptr section AND
+     flagword flags)
+{
+  if ((flags & bfd_applicable_section_flags (abfd)) != flags) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  section->flags = flags;
+  return true;
+}
+
+
+/*proto* bfd_map_over_sections
+Calls the provided function @var{func} for each section attatched to
+the bfd @var{abfd}, passing @var{obj} as an argument. The function
+will be called as if by 
+
+@example
+  func(abfd, the_section, obj);
+@end example
+
+
+*; PROTO(void, bfd_map_over_sections,
+            (bfd *abfd, void (*func)(), PTR obj));
+
+This is the prefered method for iterating over sections, an
+alternative would be to use a loop:
+
+@example
+   section *p;
+   for (p = abfd->sections; p != NULL; p = p->next)
+      func(abfd, p, ...)
+@end example
+*/
+
+/*VARARGS2*/
+void
+DEFUN(bfd_map_over_sections,(abfd, operation, user_storage),
+      bfd *abfd AND
+      void (*operation)() AND
+      PTR user_storage)
+{
+  asection *sect;
+  int i = 0;
+  
+  for (sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    (*operation) (abfd, sect, user_storage);
+
+  if (i != abfd->section_count)         /* Debugging */
+    abort();
+}
+
+
+/*proto* bfd_set_section_size
+Sets @var{section} to the size @var{val}. If the operation is ok, then
+@code{true} is returned, else @code{false}. 
+
+Possible error returns:
+@table @code
+@item invalid_operation
+Writing has started to the bfd, so setting the size is invalid
+@end table 
+
+*; PROTO(boolean, bfd_set_section_size,
+     (bfd *, asection *, bfd_size_type val));
+*/
+
+boolean
+DEFUN(bfd_set_section_size,(abfd, ptr, val),
+      bfd *abfd AND
+      sec_ptr ptr AND
+      unsigned long val)
+{
+  /* Once you've started writing to any section you cannot create or change
+     the size of any others. */
+
+  if (abfd->output_has_begun) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  ptr->size = val;
+  
+  return true;
+}
+
+/*proto* bfd_set_section_contents
+Sets the contents of the section @var{section} in bfd @var{abfd} to
+the data starting in memory at @var{data}. The data is written to the
+output section starting at offset @var{offset} for @var{count} bytes.
+
+Normally @code{true} is returned, else @code{false}. Possible error
+returns are:
+@table @code
+@item no_contents
+The output section does not have the @code{SEC_HAS_CONTENTS}
+attribute, so nothing can be written to it.
+@item and some more too
+@end table
+This routine is front end to the back end function @code{_bfd_set_section_contents}.
+
+*; PROTO(boolean, bfd_set_section_contents,
+         (bfd *abfd,        
+         asection *section,
+         PTR data,
+         file_ptr offset,
+         bfd_size_type count));
+
+*/
+
+boolean
+DEFUN(bfd_set_section_contents,(abfd, section, location, offset, count),
+      bfd *abfd AND
+      sec_ptr section AND
+      PTR location AND
+      file_ptr offset AND
+      bfd_size_type count)
+{
+  if (!(bfd_get_section_flags(abfd, section) & SEC_HAS_CONTENTS)) 
+      {
+        bfd_error = no_contents;
+        return(false);
+      } 
+
+  if (BFD_SEND (abfd, _bfd_set_section_contents,
+                (abfd, section, location, offset, count))) 
+      {
+        abfd->output_has_begun = true;
+        return true;
+      }
+
+  return false;
+}
+
+/*proto* bfd_get_section_contents
+This function reads data from @var{section} in bfd @var{abfd} into
+memory starting at @var{location}. The data is read at an offset of
+@var{offset} from the start of the input section, and is read for
+@var{count} bytes.
+
+If the contents of a constuctor with the @code{SEC_CONSTUCTOR} flag
+set are requested, then the @var{location} is filled with zeroes.
+
+If no errors occur, @code{true} is returned, else @code{false}.
+Possible errors are:
+
+@table @code
+@item unknown yet
+@end table
+
+*; PROTO(boolean, bfd_get_section_contents, 
+        (bfd *abfd, asection *section, PTR location,
+         file_ptr offset, bfd_size_type count));
+
+
+*/
+boolean
+DEFUN(bfd_get_section_contents,(abfd, section, location, offset, count),
+      bfd *abfd AND
+      sec_ptr section AND
+      PTR location AND
+      file_ptr offset AND
+      bfd_size_type count)
+{
+  if (section->flags & SEC_CONSTRUCTOR) 
+      {
+        memset(location, 0, (unsigned)count);
+        return true;
+      }
+  else 
+      {
+        return  (BFD_SEND (abfd, _bfd_get_section_contents,
+                           (abfd, section, location, offset, count)));
+      }
+}
+