⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ieee.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* BFD back-end for ieee-695 objects.   Copyright 1990, 1991, 1992 Free Software Foundation, Inc.   Written by Steve Chamberlain of Cygnus Support.This file is part of BFD, the Binary File Descriptor library.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */#define KEEPMINUSPCININST 1/* IEEE 695 format is a stream of records, which we parse using a simple one-   token (which is one byte in this lexicon) lookahead recursive decent   parser.  */#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#include "ieee.h"#include "libieee.h"#include "obstack.h"#define obstack_chunk_alloc bfd_xmalloc#define obstack_chunk_free free/* Functions for writing to ieee files in the strange way that the   standard requires. */static voidDEFUN(ieee_write_byte,(abfd, byte),      bfd *abfd AND      bfd_byte byte){  bfd_write((PTR)&byte, 1, 1, abfd);}static voidDEFUN(ieee_write_twobyte,(abfd, twobyte),      bfd *abfd AND      int twobyte){  bfd_byte b[2];  b[1] = twobyte & 0xff;  b[0] = twobyte >> 8;  bfd_write((PTR)&b[0], 1, 2, abfd);}static voidDEFUN(ieee_write_2bytes,(abfd, bytes),      bfd *abfd AND      int bytes){  bfd_byte buffer[2];  buffer[0] = bytes >> 8;  buffer[1] = bytes & 0xff;  bfd_write((PTR)buffer, 1, 2, abfd);}static voidDEFUN(ieee_write_int,(abfd, value),      bfd *abfd AND      bfd_vma value){  if (((unsigned)value) <= 127) {    ieee_write_byte(abfd, value);  }  else {    unsigned int length;    /* How many significant bytes ? */    /* FIXME FOR LONGER INTS */    if (value & 0xff000000) {      length = 4;    }    else if (value & 0x00ff0000) {      length  = 3;    }    else if (value & 0x0000ff00) {      length = 2;    }    else length = 1;    ieee_write_byte(abfd, (int)ieee_number_repeat_start_enum + length);    switch (length) {    case 4:      ieee_write_byte(abfd, value >> 24);    case 3:      ieee_write_byte(abfd, value >> 16);    case 2:      ieee_write_byte(abfd, value >> 8);    case 1:      ieee_write_byte(abfd, value);    }  }}static voidDEFUN(ieee_write_id,(abfd, id),      bfd *abfd AND      CONST char *id){  size_t length = strlen(id);  if (length >= 0 && length <= 127) {    ieee_write_byte(abfd, length);  }  else if (length < 255) {    ieee_write_byte(abfd, ieee_extension_length_1_enum);    ieee_write_byte(abfd, length);  }  else if (length < 65535) {    ieee_write_byte(abfd, ieee_extension_length_2_enum);    ieee_write_byte(abfd, length >> 8);    ieee_write_byte(abfd, length & 0xff);    }  else {    BFD_FAIL();  }  bfd_write((PTR)id, 1, length, abfd);}/***************************************************************************Functions for reading from ieee files in the strange way that thestandard requires:*/#define this_byte(ieee) *((ieee)->input_p)#define next_byte(ieee) ((ieee)->input_p++)#define this_byte_and_next(ieee) (*((ieee)->input_p++))static unsigned short DEFUN(read_2bytes,(ieee),   common_header_type *ieee){  unsigned  char c1 = this_byte_and_next(ieee);  unsigned  char c2 = this_byte_and_next(ieee);  return (c1<<8 ) | c2;}static voidDEFUN(bfd_get_string,(ieee, string, length),    common_header_type *ieee AND      char *string AND      size_t length){  size_t i;  for (i= 0; i < length; i++) {    string[i] = this_byte_and_next(ieee);  }}static char *DEFUN(read_id,(ieee),  common_header_type *ieee){  size_t length;  char *string;  length = this_byte_and_next(ieee);  if (length >= 0x00 && length <= 0x7f) {    /* Simple string of length 0 to 127 */  }  else if (length == 0xde) {    /* Length is next byte, allowing 0..255 */    length = this_byte_and_next(ieee);  }  else if (length == 0xdf) {    /* Length is next two bytes, allowing 0..65535 */    length = this_byte_and_next(ieee) ;    length = (length * 256) + this_byte_and_next(ieee);  }  /* Buy memory and read string */  string = bfd_alloc(ieee->abfd, length+1);  bfd_get_string(ieee, string, length);  string[length] = 0;  return string;}static voidDEFUN(ieee_write_expression,(abfd, value, symbol, pcrel, index),      bfd*abfd AND      bfd_vma value AND      asymbol *symbol AND      boolean pcrel AND    unsigned int index){  unsigned int term_count = 0;  if (value != 0)   {    ieee_write_int(abfd, value);    term_count++;  }         if (symbol->section == &bfd_com_section      || symbol->section == &bfd_und_section)   {    /* Def of a common symbol */    ieee_write_byte(abfd, ieee_variable_X_enum);    ieee_write_int(abfd, symbol->value);    term_count++;  }  else  if (symbol->section != &bfd_abs_section)   {    /* Ref to defined symbol - */      ieee_write_byte(abfd, ieee_variable_R_enum);    ieee_write_byte(abfd, symbol->section->index + IEEE_SECTION_NUMBER_BASE);    term_count++;    if (symbol->flags & BSF_GLOBAL)     {      ieee_write_byte(abfd, ieee_variable_I_enum);      ieee_write_int(abfd, symbol->value);      term_count++;    }    else if (symbol->flags & ( BSF_LOCAL | BSF_SECTION_SYM))    {      /* This is a reference to a defined local symbol, 	 We can easily do a local as a section+offset */      ieee_write_byte(abfd, ieee_variable_R_enum); /* or L */      ieee_write_byte(abfd, symbol->section->index +		      IEEE_SECTION_NUMBER_BASE);      ieee_write_int(abfd, symbol->value);      term_count++;    }    else   {	BFD_FAIL();      }  }     if(pcrel) {      /* subtract the pc from here by asking for PC of this section*/      ieee_write_byte(abfd, ieee_variable_P_enum);      ieee_write_byte(abfd, index  +IEEE_SECTION_NUMBER_BASE);      ieee_write_byte(abfd, ieee_function_minus_enum);    }  if (term_count == 1)   {    ieee_write_byte(abfd,0);  }  else {          while (term_count > 1) {	  ieee_write_byte(abfd, ieee_function_plus_enum);	  term_count--;	}    }}/*****************************************************************************//*writes any integer into the buffer supplied and always takes 5 bytes*/static voidDEFUN(ieee_write_int5,(buffer, value),      bfd_byte*buffer AND      bfd_vma value ){  buffer[0] = (bfd_byte)ieee_number_repeat_4_enum;  buffer[1] = (value >> 24 ) & 0xff;  buffer[2] = (value >> 16 ) & 0xff;  buffer[3] = (value >> 8 ) & 0xff;  buffer[4] = (value >> 0 ) & 0xff;}static voidDEFUN(ieee_write_int5_out, (abfd, value),      bfd *abfd AND      bfd_vma value){  bfd_byte b[5];  ieee_write_int5(b, value);  bfd_write((PTR)b,1,5,abfd);}static boolean DEFUN(parse_int,(ieee, value_ptr),      common_header_type  *ieee AND      bfd_vma *value_ptr){  int value = this_byte(ieee);  int result;  if (value >= 0 && value <= 127) {    *value_ptr = value;    next_byte(ieee);    return true;  }   else if (value >= 0x80 && value <= 0x88) {    unsigned int count = value & 0xf;    result = 0;    next_byte(ieee);    while (count) {      result =(result << 8) | this_byte_and_next(ieee);      count--;    }    *value_ptr = result;    return true;  }   return false;}static intDEFUN(parse_i,(ieee, ok),   common_header_type *ieee AND      boolean *ok){  bfd_vma x;  *ok = parse_int(ieee, &x);  return x;}static bfd_vma DEFUN(must_parse_int,(ieee),     common_header_type *ieee){  bfd_vma result;  BFD_ASSERT(parse_int(ieee, &result) == true);  return result;}typedef struct {  bfd_vma value;  asection *section;  ieee_symbol_index_type symbol;} ieee_value_type;static reloc_howto_type abs32_howto  = HOWTO(1,0,2,32,false,0,false,true,0,"abs32",true,0xffffffff, 0xffffffff,false);staticreloc_howto_type abs16_howto  = HOWTO(1,0,1,16,false,0,false,true,0,"abs16",true,0x0000ffff, 0x0000ffff,false);staticreloc_howto_type abs8_howto  = HOWTO(1,0,0,8,false,0,false,true,0,"abs8",true,0x000000ff, 0x000000ff,false);static reloc_howto_type rel32_howto  = HOWTO(1,0,2,32,true,0,false,true,0,"rel32",true,0xffffffff,	 0xffffffff,false);staticreloc_howto_type rel16_howto  = HOWTO(1,0,1,16,true,0,false,true,0,"rel16",true,0x0000ffff, 0x0000ffff,false);staticreloc_howto_type rel8_howto  = HOWTO(1,0,0,8,true,0,false,true,0,"rel8",true,0x000000ff, 0x000000ff,false);static ieee_symbol_index_type NOSYMBOL = {  0, 0};static voidDEFUN(parse_expression,(ieee, value, symbol, pcrel, extra, section),      ieee_data_type *ieee AND      bfd_vma *value AND      ieee_symbol_index_type *symbol AND      boolean *pcrel AND      unsigned int *extra AND      asection **section){#define POS sp[1]#define TOS sp[0]#define NOS sp[-1]#define INC sp++;#define DEC sp--;    boolean loop = true;  ieee_value_type stack[10];  /* The stack pointer always points to the next unused location */#define PUSH(x,y,z) TOS.symbol=x;TOS.section=y;TOS.value=z;INC;#define POP(x,y,z) DEC;x=TOS.symbol;y=TOS.section;z=TOS.value;  ieee_value_type *sp = stack;  while (loop) {    switch (this_byte(&(ieee->h))) 	{	case ieee_variable_P_enum:	  /* P variable, current program counter for section n */	    {	      int section_n ;	      next_byte(&(ieee->h));	      *pcrel = true;	      section_n  = must_parse_int(&(ieee->h));	      PUSH(NOSYMBOL, &bfd_abs_section,		   TOS.value = ieee->section_table[section_n]->vma +		   ieee_per_section(ieee->section_table[section_n])->pc);	      break;	    }	case ieee_variable_L_enum:	  /* L variable  address of section N */	  next_byte(&(ieee->h));	  PUSH(NOSYMBOL,ieee->section_table[must_parse_int(&(ieee->h))],0);	  break;	case ieee_variable_R_enum:	  /* R variable, logical address of section module */	  /* FIXME, this should be different to L */	  next_byte(&(ieee->h));	  PUSH(NOSYMBOL,ieee->section_table[must_parse_int(&(ieee->h))],0);	  break;	case ieee_variable_S_enum:	  /* S variable, size in MAUS of section module */	  next_byte(&(ieee->h));	  PUSH(NOSYMBOL,	       0,	       ieee->section_table[must_parse_int(&(ieee->h))]->_raw_size);	  break;	  case ieee_variable_I_enum:	case ieee_variable_X_enum:	  /* Push the address of external variable n */	    {	      ieee_symbol_index_type sy;	      next_byte(&(ieee->h));	      sy.index  = (int)(must_parse_int(&(ieee->h))) ;	      sy.letter = 'X';	      PUSH(sy, &bfd_und_section, 0);	    }		  break;	case ieee_function_minus_enum:	    {	      bfd_vma value1, value2;	      asection *section1, *section_dummy;	      ieee_symbol_index_type sy;	      next_byte(&(ieee->h));	      POP(sy, section1, value1);	      POP(sy, section_dummy, value2);	      PUSH(sy, section1 ? section1 : section_dummy, value1-value2);	    }	  break;	case ieee_function_plus_enum:	    {	      bfd_vma value1, value2;	      asection *section1;	      asection *section2;	      ieee_symbol_index_type sy1;	      ieee_symbol_index_type sy2;	      next_byte(&(ieee->h));	      POP(sy1, section1, value1);	      POP(sy2, section2, value2);	      PUSH(sy1.letter ? sy1 : sy2, section1!=&bfd_abs_section ? section1: section2, value1+value2);	    }	  break;	default: 	    {	      bfd_vma va;	      BFD_ASSERT(this_byte(&(ieee->h)) < (int)ieee_variable_A_enum 			 || this_byte(&(ieee->h)) > (int)ieee_variable_Z_enum);	      if (parse_int(&(ieee->h), &va)) 		  {		    PUSH(NOSYMBOL, &bfd_abs_section, va);		  }	      else {		/* 		  Thats all that we can understand. As far as I can see		  there is a bug in the Microtec IEEE output which I'm		  using to scan, whereby the comma operator is ommited		  sometimes in an expression, giving expressions with too		  many terms. We can tell if that's the case by ensuring		  that sp == stack here. If not, then we've pushed		  something too far, so we keep adding		  */		while (sp != stack+1) {		  asection *section1;		  ieee_symbol_index_type sy1;		  POP(sy1, section1, *extra);		}	      {		asection *dummy;		POP(*symbol, dummy, *value);		if (section) *section = dummy;	      }				loop = false;	      }	    }	}  }}#define ieee_seek(abfd, offset) \  IEEE_DATA(abfd)->h.input_p = IEEE_DATA(abfd)->h.first_byte + offset#define ieee_pos(abfd)   IEEE_DATA(abfd)->h.input_p -IEEE_DATA(abfd)->h.first_byte static unsigned int last_index;static ieee_symbol_type *DEFUN(get_symbol,(abfd, 		  ieee,  		  last_symbol,		  symbol_count,pptr,max_index		  ),      bfd *abfd AND      ieee_data_type *ieee AND      ieee_symbol_type *last_symbol AND      unsigned int *symbol_count AND		  ieee_symbol_type *** pptr AND      unsigned int *max_index

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -