aboutsummaryrefslogtreecommitdiff
path: root/bfd/bfd.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/bfd.c')
-rw-r--r--bfd/bfd.c250
1 files changed, 146 insertions, 104 deletions
diff --git a/bfd/bfd.c b/bfd/bfd.c
index d93bc72..ed48b18 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -38,6 +38,7 @@ short _bfd_host_big_endian = 0x0100;
+
/** Error handling
o - Most functions return nonzero on success (check doc for
precise semantics); 0 or NULL on error.
@@ -62,9 +63,25 @@ char *bfd_errmsgs[] = {"No error",
"File format not recognized",
"File format is ambiguous",
"Section has no contents",
+ "Nonrepresentable section on output",
"#<Invalid error code>"
};
+
+static
+void
+DEFUN(bfd_nonrepresentable_section,(abfd, name),
+ CONST bfd * CONST abfd AND
+ CONST char * CONST name)
+{
+ printf("bfd error writing file %s, can't represent section name %s\n", abfd->filename, name);
+ exit(1);
+}
+bfd_error_vector_type bfd_error_vector =
+ {
+ bfd_nonrepresentable_section
+ };
+
#if !defined(ANSI_LIBRARIES)
char *
strerror (code)
@@ -78,6 +95,8 @@ strerror (code)
}
#endif /* not ANSI_LIBRARIES */
+
+
char *
bfd_errmsg (error_tag)
bfd_ec error_tag;
@@ -94,6 +113,15 @@ bfd_errmsg (error_tag)
return bfd_errmsgs [(int)error_tag];
}
+
+void bfd_default_error_trap(error_tag)
+bfd_ec error_tag;
+{
+ printf("bfd assert fail (%s)\n", bfd_errmsg(error_tag));
+}
+
+void (*bfd_error_trap)() = bfd_default_error_trap;
+void (*bfd_error_nonrepresentabltrap)() = bfd_default_error_trap;
void
bfd_perror (message)
char *message;
@@ -135,12 +163,12 @@ extern bfd_target *target_vector[];
will cause the first entry in the target list to be returned. */
bfd_target *
-bfd_find_target (target_name)
- char *target_name;
+DEFUN(bfd_find_target,(target_name),
+ CONST char *target_name)
{
bfd_target **target;
extern char *getenv ();
- char *targname = (target_name ? target_name : getenv ("GNUTARGET"));
+ CONST char *targname = (target_name ? target_name : getenv ("GNUTARGET"));
/* This is safe; the vector cannot be null */
if (targname == NULL || !strcmp (targname, "default"))
@@ -247,6 +275,15 @@ bfd_check_format (abfd, format)
if (temp) { /* This format checks out as ok! */
right_targ = temp;
match_count++;
+#ifdef GNU960
+ /* Big- and little-endian b.out archives look the same, but it doesn't
+ * matter: there is no difference in their headers, and member file byte
+ * orders will (I hope) be handled appropriately by bfd. Ditto for big
+ * and little coff archives. And the 4 coff/b.out object formats are
+ * unambiguous. So accept the first match we find.
+ */
+ break;
+#endif
}
}
@@ -298,9 +335,9 @@ bfd_set_format (abfd, format)
/* Hack object and core file sections */
sec_ptr
-bfd_get_section_by_name (abfd, name)
- bfd *abfd;
- char *name;
+DEFUN(bfd_get_section_by_name,(abfd, name),
+ bfd *abfd AND
+ CONST char *name)
{
asection *sect;
@@ -312,9 +349,9 @@ bfd_get_section_by_name (abfd, name)
/* If you try to create a section with a name which is already in use,
returns the old section by that name instead. */
sec_ptr
-bfd_make_section (abfd, name)
- bfd *abfd;
- char *name;
+DEFUN(bfd_make_section,(abfd, name),
+ bfd *abfd AND
+ CONST char *name)
{
asection *newsect;
asection ** prev = &abfd->sections;
@@ -367,7 +404,7 @@ void
bfd_map_over_sections (abfd, operation, user_storage)
bfd *abfd;
void (*operation)();
- void *user_storage;
+ PTR user_storage;
{
asection *sect;
int i = 0;
@@ -418,7 +455,7 @@ boolean
bfd_set_section_contents (abfd, section, location, offset, count)
bfd *abfd;
sec_ptr section;
-void *location;
+ PTR location;
file_ptr offset;
int count;
{
@@ -441,7 +478,7 @@ boolean
bfd_get_section_contents (abfd, section, location, offset, count)
bfd *abfd;
sec_ptr section;
- void *location;
+ PTR location;
file_ptr offset;
int count;
{
@@ -544,7 +581,7 @@ bfd_canonicalize_reloc (abfd, asect, location, symbols)
void
bfd_print_symbol_vandf(file, symbol)
-void *file;
+PTR file;
asymbol *symbol;
{
flagword type = symbol->flags;
@@ -625,18 +662,16 @@ bfd_perform_relocation(abfd,
output_bfd)
bfd *abfd;
arelent *reloc_entry;
-void *data;
+PTR data;
asection *input_section;
bfd *output_bfd;
{
bfd_vma relocation;
bfd_reloc_status_enum_type flag = bfd_reloc_ok;
bfd_vma relocation_before;
- bfd_vma mask;
- bfd_vma target_mask;
bfd_vma addr = reloc_entry->address ;
bfd_vma output_base = 0;
- struct rint_struct *howto = reloc_entry->howto;
+ CONST struct rint_struct *howto = reloc_entry->howto;
asection *reloc_target_output_section;
asection *reloc_target_input_section;
asymbol *symbol;
@@ -651,7 +686,7 @@ bfd *output_bfd;
symbol = (asymbol*)NULL;
}
- if (howto->special_function) {
+ if (howto->special_function){
bfd_reloc_status_enum_type cont;
cont = howto->special_function(abfd,
reloc_entry,
@@ -662,9 +697,9 @@ bfd *output_bfd;
}
/*
- Work out which section the relocation is targetted at and the
- initial relocation command value.
- */
+ Work out which section the relocation is targetted at and the
+ initial relocation command value.
+ */
if (symbol != (asymbol *)NULL){
@@ -675,18 +710,18 @@ bfd *output_bfd;
relocation = symbol->value;
}
if (symbol->section != (asection *)NULL)
- {
- reloc_target_input_section = symbol->section;
- }
+ {
+ 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;
- }
+ {
+ relocation = 0;
+ reloc_target_input_section = reloc_entry->section;
+ }
else {
relocation = 0;
reloc_target_input_section = (asection *)NULL;
@@ -713,29 +748,29 @@ bfd *output_bfd;
if(reloc_entry->address > (bfd_vma)(input_section->size))
- {
- return bfd_reloc_outofrange;
- }
+ {
+ return bfd_reloc_outofrange;
+ }
if (howto->pc_relative == true)
- {
- /*
- Anything which started out as pc relative should end up that
- way too
- */
+ {
+ /*
+ Anything which started out as pc relative should end up that
+ way too
+ */
- relocation -=
- output_base + input_section->output_offset;
+ relocation -=
+ output_base + input_section->output_offset;
- }
+ }
if (output_bfd!= (bfd *)NULL && 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.
- */
+ 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) {
@@ -750,82 +785,89 @@ bfd *output_bfd;
/*
- 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)
- */
+ 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;
- if (howto->bitsize == 32) {
- mask = ~0;
- }
- else {
- mask = (1L << howto->bitsize) - 1 ;
- mask |= mask - 1; /* FIXME, what is this? */
- }
-
- relocation &= mask;
/* Shift everything up to where it's going to be used */
relocation <<= howto->bitpos;
- mask <<= howto->bitpos;
- target_mask = ~mask;
- /* Wait for the day when all have the mask in them */
- BFD_ASSERT(howto->mask == mask);
+ /* Wait for the day when all have the mask in them */
relocation_before = relocation;
- switch (howto->size)
- {
- case 0:
- {
- char x = bfd_getchar(abfd, (char *)data + addr);
- relocation += x & mask;
- bfd_putchar(abfd,
- ( x & target_mask) | ( relocation & mask),
- (unsigned char *) data + addr);
- }
- break;
-
- case 1:
- {
- short x = bfd_getshort(abfd, (bfd_byte *)data + addr);
- relocation += x & mask;
- bfd_putshort(abfd, ( x & target_mask) | (relocation & mask),
- (unsigned char *)data + addr);
- }
- break;
- case 2:
- {
- long x = bfd_getlong(abfd, (bfd_byte *) data + addr);
- relocation += x & mask;
- bfd_putlong(abfd, ( x & target_mask) | (relocation & mask),
- (bfd_byte *)data + addr);
- }
- break;
- case 3:
- /* Do nothing */
- break;
- default:
- return bfd_reloc_other;
- }
+ /* 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>
+ */
- /* See if important parts of the relocation were chopped to make
- it fit into the relocation field. (ie are there any significant
- bits left over after the masking ? */
- if ((relocation_before & target_mask) != 0 &&
- howto->complain_on_overflow == true)
- {
- /* Its ok if the bit which fell off is */
- return bfd_reloc_overflow;
- }
+#define DOIT(x) \
+ x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = bfd_getchar(abfd, (char *)data + addr);
+ DOIT(x);
+ bfd_putchar(abfd,x, (unsigned char *) data + addr);
+ }
+ break;
+
+ case 1:
+ {
+ short x = bfd_getshort(abfd, (bfd_byte *)data + addr);
+ DOIT(x);
+ bfd_putshort(abfd, x, (unsigned char *)data + addr);
+ }
+ break;
+ case 2:
+ {
+ long x = bfd_getlong(abfd, (bfd_byte *) data + addr);
+DOIT(x);
+ bfd_putlong(abfd,x, (bfd_byte *)data + addr);
+ }
+ break;
+ case 3:
+ /* Do nothing */
+ break;
+ default:
+ return bfd_reloc_other;
+ }
}
-
return flag;
}