versados.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 902 行 · 第 1/2 页
C
902 行
/* BFD back-end for VERSAdos-E objects. Copyright 1995, 1996, 1998, 1999, 2000 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>. Versados is a Motorola trademark. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* SUBSECTION VERSAdos-E relocateable object file format DESCRIPTION This module supports reading of VERSAdos relocateable object files. A VERSAdos file looks like contains o Indentification Record o External Symbol Definition Record o Object Text Recrod o End Record */#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#include "libiberty.h"static boolean versados_mkobject PARAMS ((bfd *));static boolean versados_scan PARAMS ((bfd *));static const bfd_target *versados_object_p PARAMS ((bfd *));#define VHEADER '1'#define VESTDEF '2'#define VOTR '3'#define VEND '4'#define ES_BASE 17 /* first symbol has esdid 17 *//* Per file target dependent information *//* one for each section */struct esdid { asection *section; /* ptr to bfd version */ unsigned char *contents; /* used to build image */ int pc; int relocs; /* reloc count, valid end of pass 1 */ int donerel; /* have relocs been translated */ };typedef struct versados_data_struct { int es_done; /* count of symbol index, starts at ES_BASE */ asymbol *symbols; /* pointer to local symbols */ char *strings; /* strings of all the above */ int stringlen; /* len of string table (valid end of pass1) */ int nsecsyms; /* number of sections */ int ndefs; /* number of exported symbols (they dont get esdids) */ int nrefs; /* number of imported symbols (valid end of pass1) */ int ref_idx; /* current processed value of the above */ int def_idx; int pass_2_done; struct esdid e[16]; /* per section info */ int alert; /* to see if we're trampling */ asymbol *rest[256 - 16]; /* per symbol info */ }tdata_type;#define VDATA(abfd) (abfd->tdata.versados_data)#define EDATA(abfd, n) (abfd->tdata.versados_data->e[n])#define RDATA(abfd, n) (abfd->tdata.versados_data->rest[n])struct ext_otr { unsigned char size; char type; unsigned char map[4]; unsigned char esdid; unsigned char data[200]; };struct ext_vheader { unsigned char size; char type; /* record type */ char name[10]; /* module name */ char rev; /* module rev number */ char lang; char vol[4]; char user[2]; char cat[8]; char fname[8]; char ext[2]; char time[3]; char date[3]; char rest[211]; };struct ext_esd { unsigned char size; char type; unsigned char esd_entries[1]; };#define ESD_ABS 0#define ESD_COMMON 1#define ESD_STD_REL_SEC 2#define ESD_SHRT_REL_SEC 3#define ESD_XDEF_IN_SEC 4#define ESD_XREF_SYM 7#define ESD_XREF_SEC 6#define ESD_XDEF_IN_ABS 5union ext_any { unsigned char size; struct ext_vheader header; struct ext_esd esd; struct ext_otr otr; };/* Initialize by filling in the hex conversion array. *//* Set up the tdata information. */static booleanversados_mkobject (abfd) bfd *abfd;{ if (abfd->tdata.versados_data == NULL) { tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type)); if (tdata == NULL) return false; abfd->tdata.versados_data = tdata; tdata->symbols = NULL; VDATA (abfd)->alert = 0x12345678; } bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0); return true;}/* Report a problem in an S record file. FIXME: This probably should not call fprintf, but we really do need some mechanism for printing error messages. */static asymbol *versados_new_symbol (abfd, snum, name, val, sec) bfd *abfd; int snum; const char *name; bfd_vma val; asection *sec;{ asymbol *n = VDATA (abfd)->symbols + snum; n->name = name; n->value = val; n->section = sec; n->the_bfd = abfd; n->flags = 0; return n;}static intget_record (abfd, ptr) bfd *abfd; union ext_any *ptr;{ bfd_read (&ptr->size, 1, 1, abfd); if (bfd_read ((char *) ptr + 1, 1, ptr->size, abfd) != ptr->size) return 0; return 1;}intget_4 (pp) unsigned char **pp;{ unsigned char *p = *pp; *pp += 4; return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);}voidget_10 (pp, name) unsigned char **pp; char *name;{ char *p = (char *) *pp; int len = 10; *pp += len; while (*p != ' ' && len) { *name++ = *p++; len--; } *name = 0;}static char *new_symbol_string (abfd, name) bfd *abfd; char *name;{ char *n = VDATA (abfd)->strings; strcpy (VDATA (abfd)->strings, name); VDATA (abfd)->strings += strlen (VDATA (abfd)->strings) + 1; return n;}static voidprocess_esd (abfd, esd, pass) bfd *abfd; struct ext_esd *esd; int pass;{ /* Read through the ext def for the est entries */ int togo = esd->size - 2; bfd_vma size; bfd_vma start; asection *sec; char name[11]; unsigned char *ptr = esd->esd_entries; unsigned char *end = ptr + togo; while (ptr < end) { int scn = *ptr & 0xf; int typ = (*ptr >> 4) & 0xf; /* Declare this section */ sprintf (name, "%d", scn); sec = bfd_make_section_old_way (abfd, strdup (name)); sec->target_index = scn; EDATA (abfd, scn).section = sec; ptr++; switch (typ) { default: abort (); case ESD_XREF_SEC: case ESD_XREF_SYM: { int snum = VDATA (abfd)->ref_idx++; get_10 (&ptr, name); if (pass == 1) { VDATA (abfd)->stringlen += strlen (name) + 1; } else { int esidx; asymbol *s; char *n = new_symbol_string (abfd, name); s = versados_new_symbol (abfd, snum, n, 0, &bfd_und_section, scn); esidx = VDATA (abfd)->es_done++; RDATA (abfd, esidx - ES_BASE) = s; } } break; case ESD_ABS: size = get_4 (&ptr); start = get_4 (&ptr); break; case ESD_STD_REL_SEC: case ESD_SHRT_REL_SEC: { sec->_raw_size = get_4 (&ptr); sec->flags |= SEC_ALLOC; } break; case ESD_XDEF_IN_ABS: sec = (asection *) & bfd_abs_section; case ESD_XDEF_IN_SEC: { int snum = VDATA (abfd)->def_idx++; long val; get_10 (&ptr, name); val = get_4 (&ptr); if (pass == 1) { /* Just remember the symbol */ VDATA (abfd)->stringlen += strlen (name) + 1; } else { asymbol *s; char *n = new_symbol_string (abfd, name); s = versados_new_symbol (abfd, snum + VDATA (abfd)->nrefs, n, val, sec, scn); s->flags |= BSF_GLOBAL; } } break; } }}#define R_RELWORD 1#define R_RELLONG 2#define R_RELWORD_NEG 3#define R_RELLONG_NEG 4reloc_howto_type versados_howto_table[] ={ HOWTO (R_RELWORD, 0, 1, 16, false, 0, complain_overflow_dont, 0, "+v16", true, 0x0000ffff, 0x0000ffff, false), HOWTO (R_RELLONG, 0, 2, 32, false, 0, complain_overflow_dont, 0, "+v32", true, 0xffffffff, 0xffffffff, false), HOWTO (R_RELWORD_NEG, 0, -1, 16, false, 0, complain_overflow_dont, 0, "-v16", true, 0x0000ffff, 0x0000ffff, false), HOWTO (R_RELLONG_NEG, 0, -2, 32, false, 0, complain_overflow_dont, 0, "-v32", true, 0xffffffff, 0xffffffff, false),};static intget_offset (len, ptr) int len; unsigned char *ptr;{ int val = 0; if (len) { int i; val = *ptr++; if (val & 0x80) val |= ~0xff; for (i = 1; i < len; i++) val = (val << 8) | *ptr++; } return val;}static voidprocess_otr (abfd, otr, pass) bfd *abfd; struct ext_otr *otr; int pass;{ unsigned long shift; unsigned char *srcp = otr->data; unsigned char *endp = (unsigned char *) otr + otr->size; unsigned int bits = (otr->map[0] << 24) | (otr->map[1] << 16) | (otr->map[2] << 8) | (otr->map[3] << 0); struct esdid *esdid = &EDATA (abfd, otr->esdid - 1); unsigned char *contents = esdid->contents; int need_contents = 0; unsigned int dst_idx = esdid->pc; for (shift = (1 << 31); shift && srcp < endp; shift >>= 1) { if (bits & shift) { int flag = *srcp++; int esdids = (flag >> 5) & 0x7; int sizeinwords = ((flag >> 3) & 1) ? 2 : 1; int offsetlen = flag & 0x7; int j; if (esdids == 0) { /* A zero esdid means the new pc is the offset given */ dst_idx += get_offset (offsetlen, srcp); srcp += offsetlen; } else { int val = get_offset (offsetlen, srcp + esdids); if (pass == 1) need_contents = 1; else for (j = 0; j < sizeinwords * 2; j++) { contents[dst_idx + (sizeinwords * 2) - j - 1] = val; val >>= 8; } for (j = 0; j < esdids; j++) { int esdid = *srcp++; if (esdid) { int rn = EDATA (abfd, otr->esdid - 1).relocs++; if (pass == 1) { /* this is the first pass over the data, just remember that we need a reloc */ } else { arelent *n = EDATA (abfd, otr->esdid - 1).section->relocation + rn; n->address = dst_idx; n->sym_ptr_ptr = (asymbol **) esdid; n->addend = 0; n->howto = versados_howto_table + ((j & 1) * 2) + (sizeinwords - 1); } } } srcp += offsetlen; dst_idx += sizeinwords * 2; } } else { need_contents = 1; if (dst_idx < esdid->section->_raw_size) if (pass == 2) { /* absolute code, comes in 16 bit lumps */ contents[dst_idx] = srcp[0]; contents[dst_idx + 1] = srcp[1]; } dst_idx += 2; srcp += 2; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?