From 985fca129365a7bfa8e8e91b4d8b57d65f308583 Mon Sep 17 00:00:00 2001 From: Steve Chamberlain Date: Thu, 4 Jul 1991 16:52:19 +0000 Subject: [PATCH] Initial revision --- bfd/core.c | 65 ++++++ bfd/reloc.c | 612 ++++++++++++++++++++++++++++++++++++++++++++++++++ bfd/section.c | 553 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1230 insertions(+) create mode 100644 bfd/core.c create mode 100644 bfd/reloc.c create mode 100644 bfd/section.c diff --git a/bfd/core.c b/bfd/core.c new file mode 100644 index 0000000000..b4ab497ecf --- /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 0000000000..2d1f6a50c7 --- /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 + 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 + 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 + */ + +#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 0000000000..099f0bd163 --- /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 = §->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))); + } +} +