static int read_word (bfd_vma memaddr, struct disassemble_info *info, u16 arg, u16 *val) { int status; bfd_byte buffer[8]; if ((arg >= 0x10 && arg <= 0x17) || arg == 0x1a || arg == 0x1e || arg == 0x1f) { status = (*info->read_memory_func) (memaddr, buffer, 2, info); if (status != 0) { (*info->memory_error_func) (status, memaddr, info); return -1; } *val = bfd_getb16 (buffer); return 1; } return 0; }
static int print_insn_nios2 (bfd_vma address, disassemble_info *info, enum bfd_endian endianness) { bfd_byte buffer[INSNLEN]; int status; status = (*info->read_memory_func) (address, buffer, INSNLEN, info); if (status == 0) { unsigned long insn; if (endianness == BFD_ENDIAN_BIG) insn = (unsigned long) bfd_getb32 (buffer); else insn = (unsigned long) bfd_getl32 (buffer); return nios2_disassemble (address, insn, info); } /* We might have a 16-bit R2 instruction at the end of memory. Try that. */ if (info->mach == bfd_mach_nios2r2) { status = (*info->read_memory_func) (address, buffer, 2, info); if (status == 0) { unsigned long insn; if (endianness == BFD_ENDIAN_BIG) insn = (unsigned long) bfd_getb16 (buffer); else insn = (unsigned long) bfd_getl16 (buffer); return nios2_disassemble (address, insn, info); } } /* If we got here, we couldn't read anything. */ (*info->memory_error_func) (status, address, info); return -1; }
int print_insn_dcpu16 (bfd_vma memaddr, struct disassemble_info *info) { int status, result; bfd_byte buffer[8]; u16 opcode, aword, bword; const struct dcpu16_opcode *op; info->bytes_per_line = 6; info->bytes_per_chunk = 2; info->display_endian = BFD_ENDIAN_BIG; status = (*info->read_memory_func) (memaddr, buffer, 2, info); if (status != 0) { (*info->memory_error_func) (status, memaddr, info); return -1; } opcode = bfd_getb16 (buffer); result = 1; if (opcode & 0x1f) { op = lookup_instruction (opcode&0x1f); if (op) { (*info->fprintf_func) (info->stream, "%s\t", op->name); result += read_word(memaddr+result, info, opcode>>10, &aword); result += read_word(memaddr+result, info, (opcode>>5)&0x1f, &bword); print_operand(info, (opcode>>5)&0x1f, bword, 1); (*info->fprintf_func) (info->stream, ", "); print_operand(info, opcode>>10, aword, 0); } }
int print_insn_moxie (bfd_vma addr, struct disassemble_info * info) { int length = 2; int status; stream = info->stream; const moxie_opc_info_t * opcode; bfd_byte buffer[4]; unsigned short iword; fpr = info->fprintf_func; if ((status = info->read_memory_func (addr, buffer, 2, info))) goto fail; if (info->endian == BFD_ENDIAN_BIG) iword = bfd_getb16 (buffer); else iword = bfd_getl16 (buffer); /* Form 1 instructions have the high bit set to 0. */ if ((iword & (1<<15)) == 0) { /* Extract the Form 1 opcode. */ opcode = &moxie_form1_opc_info[iword >> 8]; switch (opcode->itype) { case MOXIE_F1_NARG: fpr (stream, "%s", opcode->name); break; case MOXIE_F1_A: fpr (stream, "%s\t%s", opcode->name, reg_names[OP_A(iword)]); break; case MOXIE_F1_AB: fpr (stream, "%s\t%s, %s", opcode->name, reg_names[OP_A(iword)], reg_names[OP_B(iword)]); break; case MOXIE_F1_A4: { unsigned imm; if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) goto fail; if (info->endian == BFD_ENDIAN_BIG) imm = bfd_getb32 (buffer); else imm = bfd_getl32 (buffer); fpr (stream, "%s\t%s, 0x%x", opcode->name, reg_names[OP_A(iword)], imm); length = 6; } break; case MOXIE_F1_4: { unsigned imm; if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) goto fail; if (info->endian == BFD_ENDIAN_BIG) imm = bfd_getb32 (buffer); else imm = bfd_getl32 (buffer); fpr (stream, "%s\t0x%x", opcode->name, imm); length = 6; } break; case MOXIE_F1_M: { unsigned imm; if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) goto fail; if (info->endian == BFD_ENDIAN_BIG) imm = bfd_getb32 (buffer); else imm = bfd_getl32 (buffer); fpr (stream, "%s\t", opcode->name); info->print_address_func ((bfd_vma) imm, info); length = 6; } break; case MOXIE_F1_AiB: fpr (stream, "%s\t(%s), %s", opcode->name, reg_names[OP_A(iword)], reg_names[OP_B(iword)]); break; case MOXIE_F1_ABi: fpr (stream, "%s\t%s, (%s)", opcode->name, reg_names[OP_A(iword)], reg_names[OP_B(iword)]); break; case MOXIE_F1_4A: { unsigned imm; if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) goto fail; if (info->endian == BFD_ENDIAN_BIG) imm = bfd_getb32 (buffer); else imm = bfd_getl32 (buffer); fpr (stream, "%s\t0x%x, %s", opcode->name, imm, reg_names[OP_A(iword)]); length = 6; } break; case MOXIE_F1_AiB4: { unsigned imm; if ((status = info->read_memory_func (addr+2, buffer, 4, info))) goto fail; if (info->endian == BFD_ENDIAN_BIG) imm = bfd_getb32 (buffer); else imm = bfd_getl32 (buffer); fpr (stream, "%s\t0x%x(%s), %s", opcode->name, imm, reg_names[OP_A(iword)], reg_names[OP_B(iword)]); length = 6; } break; case MOXIE_F1_ABi4: { unsigned imm; if ((status = info->read_memory_func (addr+2, buffer, 4, info))) goto fail; if (info->endian == BFD_ENDIAN_BIG) imm = bfd_getb32 (buffer); else imm = bfd_getl32 (buffer); fpr (stream, "%s\t%s, 0x%x(%s)", opcode->name, reg_names[OP_A(iword)], imm, reg_names[OP_B(iword)]); length = 6; } break; case MOXIE_BAD: fpr (stream, "bad"); break; default: abort(); } }
static int bfd_pef_parse_traceback_table (bfd *abfd, asection *section, unsigned char *buf, size_t len, size_t pos, asymbol *sym, FILE *file) { struct traceback_table table; size_t offset; const char *s; asymbol tmpsymbol; if (sym == NULL) sym = & tmpsymbol; sym->name = NULL; sym->value = 0; sym->the_bfd = abfd; sym->section = section; sym->flags = 0; sym->udata.i = 0; /* memcpy is fine since all fields are unsigned char. */ if ((pos + 8) > len) return -1; memcpy (&table, buf + pos, 8); /* Calling code relies on returned symbols having a name and correct offset. */ if ((table.lang != TB_C) && (table.lang != TB_CPLUSPLUS)) return -1; if (! (table.flags2 & TB_NAME_PRESENT)) return -1; if (! (table.flags1 & TB_HAS_TBOFF)) return -1; offset = 8; if ((table.flags5 & TB_FLOATPARAMS) || (table.fixedparams)) offset += 4; if (table.flags1 & TB_HAS_TBOFF) { struct traceback_table_tboff off; if ((pos + offset + 4) > len) return -1; off.tb_offset = bfd_getb32 (buf + pos + offset); offset += 4; /* Need to subtract 4 because the offset includes the 0x0L preceding the table. */ if (file != NULL) fprintf (file, " [offset = 0x%lx]", off.tb_offset); if ((file == NULL) && ((off.tb_offset + 4) > (pos + offset))) return -1; sym->value = pos - off.tb_offset - 4; } if (table.flags2 & TB_INT_HNDL) offset += 4; if (table.flags1 & TB_HAS_CTL) { struct traceback_table_anchors anchors; if ((pos + offset + 4) > len) return -1; anchors.ctl_info = bfd_getb32 (buf + pos + offset); offset += 4; if (anchors.ctl_info > 1024) return -1; offset += anchors.ctl_info * 4; } if (table.flags2 & TB_NAME_PRESENT) { struct traceback_table_routine name; char *namebuf; if ((pos + offset + 2) > len) return -1; name.name_len = bfd_getb16 (buf + pos + offset); offset += 2; if (name.name_len > 4096) return -1; if ((pos + offset + name.name_len) > len) return -1; namebuf = bfd_alloc (abfd, name.name_len + 1); if (namebuf == NULL) return -1; memcpy (namebuf, buf + pos + offset, name.name_len); namebuf[name.name_len] = '\0'; /* Strip leading period inserted by compiler. */ if (namebuf[0] == '.') memmove (namebuf, namebuf + 1, name.name_len + 1); sym->name = namebuf; for (s = sym->name; (*s != '\0'); s++) if (! ISPRINT (*s)) return -1; offset += name.name_len; } if (table.flags2 & TB_USES_ALLOCA) offset += 4; if (table.flags4 & TB_HAS_VEC_INFO) offset += 4; if (file != NULL) fprintf (file, " [length = 0x%lx]", (unsigned long) offset); return offset; }
static void build_link_order (lang_statement_union_type *statement) { switch (statement->header.type) { case lang_data_statement_enum: { asection *output_section; struct bfd_link_order *link_order; bfd_vma value; bfd_boolean big_endian = FALSE; output_section = statement->data_statement.output_section; ASSERT (output_section->owner == link_info.output_bfd); if (!((output_section->flags & SEC_HAS_CONTENTS) != 0 || ((output_section->flags & SEC_LOAD) != 0 && (output_section->flags & SEC_THREAD_LOCAL)))) break; link_order = bfd_new_link_order (link_info.output_bfd, output_section); if (link_order == NULL) einfo (_("%F%P: bfd_new_link_order failed\n")); link_order->type = bfd_data_link_order; link_order->offset = statement->data_statement.output_offset; link_order->u.data.contents = (bfd_byte *) xmalloc (QUAD_SIZE); value = statement->data_statement.value; /* If the endianness of the output BFD is not known, then we base the endianness of the data on the first input file. By convention, the bfd_put routines for an unknown endianness are big endian, so we must swap here if the input file is little endian. */ if (bfd_big_endian (link_info.output_bfd)) big_endian = TRUE; else if (bfd_little_endian (link_info.output_bfd)) big_endian = FALSE; else { bfd_boolean swap; swap = FALSE; if (command_line.endian == ENDIAN_BIG) big_endian = TRUE; else if (command_line.endian == ENDIAN_LITTLE) { big_endian = FALSE; swap = TRUE; } else if (command_line.endian == ENDIAN_UNSET) { big_endian = TRUE; { LANG_FOR_EACH_INPUT_STATEMENT (s) { if (s->the_bfd != NULL) { if (bfd_little_endian (s->the_bfd)) { big_endian = FALSE; swap = TRUE; } break; } } } } if (swap) { bfd_byte buffer[8]; switch (statement->data_statement.type) { case QUAD: case SQUAD: if (sizeof (bfd_vma) >= QUAD_SIZE) { bfd_putl64 (value, buffer); value = bfd_getb64 (buffer); break; } /* Fall through. */ case LONG: bfd_putl32 (value, buffer); value = bfd_getb32 (buffer); break; case SHORT: bfd_putl16 (value, buffer); value = bfd_getb16 (buffer); break; case BYTE: break; default: abort (); } } } ASSERT (output_section->owner == link_info.output_bfd); switch (statement->data_statement.type) { case QUAD: case SQUAD: if (sizeof (bfd_vma) >= QUAD_SIZE) bfd_put_64 (link_info.output_bfd, value, link_order->u.data.contents); else { bfd_vma high; if (statement->data_statement.type == QUAD) high = 0; else if ((value & 0x80000000) == 0) high = 0; else high = (bfd_vma) -1; bfd_put_32 (link_info.output_bfd, high, (link_order->u.data.contents + (big_endian ? 0 : 4))); bfd_put_32 (link_info.output_bfd, value, (link_order->u.data.contents + (big_endian ? 4 : 0))); } link_order->size = QUAD_SIZE; break; case LONG: bfd_put_32 (link_info.output_bfd, value, link_order->u.data.contents); link_order->size = LONG_SIZE; break; case SHORT: bfd_put_16 (link_info.output_bfd, value, link_order->u.data.contents); link_order->size = SHORT_SIZE; break; case BYTE: bfd_put_8 (link_info.output_bfd, value, link_order->u.data.contents); link_order->size = BYTE_SIZE; break; default: abort (); } link_order->u.data.size = link_order->size; } break; case lang_reloc_statement_enum: { lang_reloc_statement_type *rs; asection *output_section; struct bfd_link_order *link_order; rs = &statement->reloc_statement; output_section = rs->output_section; ASSERT (output_section->owner == link_info.output_bfd); if (!((output_section->flags & SEC_HAS_CONTENTS) != 0 || ((output_section->flags & SEC_LOAD) != 0 && (output_section->flags & SEC_THREAD_LOCAL)))) break; link_order = bfd_new_link_order (link_info.output_bfd, output_section); if (link_order == NULL) einfo (_("%F%P: bfd_new_link_order failed\n")); link_order->offset = rs->output_offset; link_order->size = bfd_get_reloc_size (rs->howto); link_order->u.reloc.p = (struct bfd_link_order_reloc *) xmalloc (sizeof (struct bfd_link_order_reloc)); link_order->u.reloc.p->reloc = rs->reloc; link_order->u.reloc.p->addend = rs->addend_value; if (rs->name == NULL) { link_order->type = bfd_section_reloc_link_order; if (rs->section->owner == link_info.output_bfd) link_order->u.reloc.p->u.section = rs->section; else { link_order->u.reloc.p->u.section = rs->section->output_section; link_order->u.reloc.p->addend += rs->section->output_offset; } } else { link_order->type = bfd_symbol_reloc_link_order; link_order->u.reloc.p->u.name = rs->name; } } break; case lang_input_section_enum: { /* Create a new link_order in the output section with this attached */ asection *i = statement->input_section.section; if (i->sec_info_type != SEC_INFO_TYPE_JUST_SYMS && (i->flags & SEC_EXCLUDE) == 0) { asection *output_section = i->output_section; struct bfd_link_order *link_order; ASSERT (output_section->owner == link_info.output_bfd); if (!((output_section->flags & SEC_HAS_CONTENTS) != 0 || ((output_section->flags & SEC_LOAD) != 0 && (output_section->flags & SEC_THREAD_LOCAL)))) break; link_order = bfd_new_link_order (link_info.output_bfd, output_section); if (link_order == NULL) einfo (_("%F%P: bfd_new_link_order failed\n")); if ((i->flags & SEC_NEVER_LOAD) != 0 && (i->flags & SEC_DEBUGGING) == 0) { /* We've got a never load section inside one which is going to be output, we'll change it into a fill. */ link_order->type = bfd_data_link_order; link_order->u.data.contents = (unsigned char *) ""; link_order->u.data.size = 1; } else { link_order->type = bfd_indirect_link_order; link_order->u.indirect.section = i; ASSERT (i->output_section == output_section); } link_order->size = i->size; link_order->offset = i->output_offset; } } break; case lang_padding_statement_enum: /* Make a new link_order with the right filler */ { asection *output_section; struct bfd_link_order *link_order; output_section = statement->padding_statement.output_section; ASSERT (statement->padding_statement.output_section->owner == link_info.output_bfd); if (!((output_section->flags & SEC_HAS_CONTENTS) != 0 || ((output_section->flags & SEC_LOAD) != 0 && (output_section->flags & SEC_THREAD_LOCAL)))) break; link_order = bfd_new_link_order (link_info.output_bfd, output_section); if (link_order == NULL) einfo (_("%F%P: bfd_new_link_order failed\n")); link_order->type = bfd_data_link_order; link_order->size = statement->padding_statement.size; link_order->offset = statement->padding_statement.output_offset; link_order->u.data.contents = statement->padding_statement.fill->data; link_order->u.data.size = statement->padding_statement.fill->size; } break; default: /* All the other ones fall through */ break; }