?? ieee.c
字號:
/* 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 + -