static bfd_vma read_value (bfd *abfd, bfd_byte *buf, int width, int is_signed) { bfd_vma value; switch (width) { case 2: if (is_signed) value = bfd_get_signed_16 (abfd, buf); else value = bfd_get_16 (abfd, buf); break; case 4: if (is_signed) value = bfd_get_signed_32 (abfd, buf); else value = bfd_get_32 (abfd, buf); break; case 8: if (is_signed) value = bfd_get_signed_64 (abfd, buf); else value = bfd_get_64 (abfd, buf); break; default: BFD_FAIL (); return 0; } return value; }
static void write_value (bfd *abfd, bfd_byte *buf, bfd_vma value, int width) { switch (width) { case 2: bfd_put_16 (abfd, value, buf); break; case 4: bfd_put_32 (abfd, value, buf); break; case 8: bfd_put_64 (abfd, value, buf); break; default: BFD_FAIL (); } }
static bfd_boolean oasys_slurp_section_data (bfd *const abfd) { oasys_record_union_type record; oasys_data_type *data = OASYS_DATA (abfd); bfd_boolean loop = TRUE; oasys_per_section_type *per; asection *s; bfd_size_type amt; /* See if the data has been slurped already. */ for (s = abfd->sections; s != NULL; s = s->next) { per = oasys_per_section (s); if (per->initialized) return TRUE; } if (data->first_data_record == 0) return TRUE; if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0) return FALSE; while (loop) { if (! oasys_read_record (abfd, &record)) return FALSE; switch (record.header.type) { case oasys_record_is_header_enum: break; case oasys_record_is_data_enum: { bfd_byte *src = record.data.data; bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length; bfd_byte *dst_ptr; bfd_byte *dst_base_ptr; unsigned int relbit; unsigned int count; asection *section = data->sections[record.data.relb & RELOCATION_SECT_BITS]; bfd_vma dst_offset; per = oasys_per_section (section); if (! per->initialized) { arelent **relpp; per->data = bfd_zalloc (abfd, section->size); if (!per->data) return FALSE; relpp = §ion->relocation; per->reloc_tail_ptr = (oasys_reloc_type **) relpp; per->had_vma = FALSE; per->initialized = TRUE; section->reloc_count = 0; section->flags = SEC_ALLOC; } dst_offset = H_GET_32 (abfd, record.data.addr); if (! per->had_vma) { /* Take the first vma we see as the base. */ section->vma = dst_offset; per->had_vma = TRUE; } dst_offset -= section->vma; dst_base_ptr = oasys_per_section (section)->data; dst_ptr = oasys_per_section (section)->data + dst_offset; if (src < end_src) section->flags |= SEC_LOAD | SEC_HAS_CONTENTS; while (src < end_src) { unsigned char mod_byte = *src++; size_t gap = end_src - src; count = 8; if (mod_byte == 0 && gap >= 8) { dst_ptr[0] = src[0]; dst_ptr[1] = src[1]; dst_ptr[2] = src[2]; dst_ptr[3] = src[3]; dst_ptr[4] = src[4]; dst_ptr[5] = src[5]; dst_ptr[6] = src[6]; dst_ptr[7] = src[7]; dst_ptr += 8; src += 8; } else { for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1) { if (relbit & mod_byte) { unsigned char reloc = *src; /* This item needs to be relocated. */ switch (reloc & RELOCATION_TYPE_BITS) { case RELOCATION_TYPE_ABS: break; case RELOCATION_TYPE_REL: { /* Relocate the item relative to the section. */ oasys_reloc_type *r; amt = sizeof (oasys_reloc_type); r = bfd_alloc (abfd, amt); if (!r) return FALSE; *(per->reloc_tail_ptr) = r; per->reloc_tail_ptr = &r->next; r->next = NULL; /* Reference to undefined symbol. */ src++; /* There is no symbol. */ r->symbol = 0; /* Work out the howto. */ abort (); r->relent.address = dst_ptr - dst_base_ptr; r->relent.howto = &howto_table[reloc >> 6]; r->relent.sym_ptr_ptr = NULL; section->reloc_count++; /* Fake up the data to look like it's got the -ve pc in it, this makes it much easier to convert into other formats. This is done by hitting the addend. */ if (r->relent.howto->pc_relative) r->relent.addend -= dst_ptr - dst_base_ptr; } break; case RELOCATION_TYPE_UND: { oasys_reloc_type *r; amt = sizeof (oasys_reloc_type); r = bfd_alloc (abfd, amt); if (!r) return FALSE; *(per->reloc_tail_ptr) = r; per->reloc_tail_ptr = &r->next; r->next = NULL; /* Reference to undefined symbol. */ src++; /* Get symbol number. */ r->symbol = (src[0] << 8) | src[1]; /* Work out the howto. */ abort (); r->relent.addend = 0; r->relent.address = dst_ptr - dst_base_ptr; r->relent.howto = &howto_table[reloc >> 6]; r->relent.sym_ptr_ptr = NULL; section->reloc_count++; src += 2; /* Fake up the data to look like it's got the -ve pc in it, this makes it much easier to convert into other formats. This is done by hitting the addend. */ if (r->relent.howto->pc_relative) r->relent.addend -= dst_ptr - dst_base_ptr; } break; case RELOCATION_TYPE_COM: BFD_FAIL (); } } *dst_ptr++ = *src++; } } } } break; case oasys_record_is_local_enum: case oasys_record_is_symbol_enum: case oasys_record_is_section_enum: break; default: loop = FALSE; } }