aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Chamberlain <steve@cygnus>1991-07-04 16:52:19 +0000
committerSteve Chamberlain <steve@cygnus>1991-07-04 16:52:19 +0000
commit985fca129365a7bfa8e8e91b4d8b57d65f308583 (patch)
tree1c1837786a6af5798ec8ae9d2a2ecfc744536bf0
parentbdf3621b9e6618e13efd3bedd3be56d32c296075 (diff)
downloadgdb-985fca129365a7bfa8e8e91b4d8b57d65f308583.zip
gdb-985fca129365a7bfa8e8e91b4d8b57d65f308583.tar.gz
gdb-985fca129365a7bfa8e8e91b4d8b57d65f308583.tar.bz2
Initial revision
-rw-r--r--bfd/core.c65
-rw-r--r--bfd/reloc.c612
-rw-r--r--bfd/section.c553
3 files changed, 1230 insertions, 0 deletions
diff --git a/bfd/core.c b/bfd/core.c
new file mode 100644
index 0000000..b4ab497
--- /dev/null
+++ b/bfd/core.c
@@ -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
index 0000000..2d1f6a5
--- /dev/null
+++ b/bfd/reloc.c
@@ -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
index 0000000..099f0bd
--- /dev/null
+++ b/bfd/section.c
@@ -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)));
+ }
+}
+