* Minimal support for reading SOM fixup streams. Allows

objdump -r to do something reasonable.
        * som.c (som_get_reloc_upper_bound): Implement.
        (som_canonicalize_reloc): Implement.
        (som_set_reloc_info, som_slurp_reloc_table): New functions.
This commit is contained in:
Jeff Law 1993-11-22 10:37:02 +00:00
parent cd4d802bbb
commit 36456a67f8
2 changed files with 808 additions and 48 deletions

View File

@ -1,3 +1,11 @@
Mon Nov 22 02:33:12 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
* Minimal support for reading SOM fixup streams. Allows
objdump -r to do something reasonable.
* som.c (som_get_reloc_upper_bound): Implement.
(som_canonicalize_reloc): Implement.
(som_set_reloc_info, som_slurp_reloc_table): New functions.
Fri Nov 19 14:34:04 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
* coff-a29k.c (a29k_reloc): For R_IREL, don't left shift

848
bfd/som.c
View File

@ -118,6 +118,11 @@ static unsigned int som_get_symtab_upper_bound PARAMS ((bfd *));
static unsigned int som_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
arelent **, asymbol **));
static unsigned int som_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
static unsigned int som_set_reloc_info PARAMS ((unsigned char *, unsigned int,
arelent *, asection *,
asymbol **, boolean));
static boolean som_slurp_reloc_table PARAMS ((bfd *, asection *,
asymbol **, boolean));
static unsigned int som_get_symtab PARAMS ((bfd *, asymbol **));
static asymbol * som_make_empty_symbol PARAMS ((bfd *));
static void som_print_symbol PARAMS ((bfd *, PTR,
@ -178,6 +183,438 @@ static boolean som_begin_writing PARAMS ((bfd *));
static const reloc_howto_type * som_bfd_reloc_type_lookup
PARAMS ((bfd_arch_info_type *, bfd_reloc_code_real_type));
/* About the relocation formatting table...
There are 256 entries in the table, one for each possible
relocation opcode available in SOM. We index the table by
the relocation opcode. The names and operations are those
defined by a.out_800 (4).
Right now this table is only used to count and perform minimal
processing on relocation streams so that they can be internalized
into BFD and symbolically printed by utilities. To make actual use
of them would be much more difficult, BFD's concept of relocations
is far too simple to handle SOM relocations. The basic assumption
that a relocation can be completely processed independent of other
relocations before an object file is written is invalid for SOM.
The SOM relocations are meant to be processed as a stream, they
specify copying of data from the input section to the output section
while possibly modifying the data in some manner. They also can
specify that a variable number of zeros or uninitialized data be
inserted on in the output segment at the current offset. Some
relocations specify that some previous relocation be re-applied at
the current location in the input/output sections. And finally a number
of relocations have effects on other sections (R_ENTRY, R_EXIT,
R_UNWIND_AUX and a variety of others). There isn't even enough room
in the BFD relocation data structure to store enough information to
perform all the relocations.
Each entry in the table has three fields.
The first entry is an index into this "class" of relocations. This
index can then be used as a variable within the relocation itself.
The second field is a format string which actually controls processing
of the relocation. It uses a simple postfix machine to do calculations
based on variables/constants found in the string and the relocation
stream.
The third field specifys whether or not this relocation may use
a constant (V) from the previous R_DATA_OVERRIDE rather than a constant
stored in the instruction.
Variables:
L = input space byte count
D = index into class of relocations
M = output space byte count
N = statement number (unused?)
O = stack operation
R = parameter relocation bits
S = symbol index
U = 64 bits of stack unwind and frame size info (we only keep 32 bits)
V = a literal constant (usually used in the next relocation)
P = a previous relocation
Lower case letters (starting with 'b') refer to following
bytes in the relocation stream. 'b' is the next 1 byte,
c is the next 2 bytes, d is the next 3 bytes, etc...
This is the variable part of the relocation entries that
makes our life a living hell.
numerical constants are also used in the format string. Note
the constants are represented in decimal.
'+', "*" and "=" represents the obvious postfix operators.
'<' represents a left shift.
Stack Operations:
Parameter Relocation Bits:
Unwind Entries:
Previous Relocations: The index field represents which in the queue
of 4 previous fixups should be re-applied.
Literal Constants: These are generally used to represent addend
parts of relocations when these constants are not stored in the
fields of the instructions themselves. For example the instruction
addil foo-$global$-0x1234 would use an override for "0x1234" rather
than storing it into the addil itself. */
struct fixup_format
{
int D;
char *format;
};
static const struct fixup_format som_fixup_formats[256] =
{
/* R_NO_RELOCATION */
0, "LD1+4*=", /* 0x00 */
1, "LD1+4*=", /* 0x01 */
2, "LD1+4*=", /* 0x02 */
3, "LD1+4*=", /* 0x03 */
4, "LD1+4*=", /* 0x04 */
5, "LD1+4*=", /* 0x05 */
6, "LD1+4*=", /* 0x06 */
7, "LD1+4*=", /* 0x07 */
8, "LD1+4*=", /* 0x08 */
9, "LD1+4*=", /* 0x09 */
10, "LD1+4*=", /* 0x0a */
11, "LD1+4*=", /* 0x0b */
12, "LD1+4*=", /* 0x0c */
13, "LD1+4*=", /* 0x0d */
14, "LD1+4*=", /* 0x0e */
15, "LD1+4*=", /* 0x0f */
16, "LD1+4*=", /* 0x10 */
17, "LD1+4*=", /* 0x11 */
18, "LD1+4*=", /* 0x12 */
19, "LD1+4*=", /* 0x13 */
20, "LD1+4*=", /* 0x14 */
21, "LD1+4*=", /* 0x15 */
22, "LD1+4*=", /* 0x16 */
23, "LD1+4*=", /* 0x17 */
0, "LD8<b+1+4*=", /* 0x18 */
1, "LD8<b+1+4*=", /* 0x19 */
2, "LD8<b+1+4*=", /* 0x1a */
3, "LD8<b+1+4*=", /* 0x1b */
0, "LD16<c+1+4*=", /* 0x1c */
1, "LD16<c+1+4*=", /* 0x1d */
2, "LD16<c+1+4*=", /* 0x1e */
0, "Ld1+=", /* 0x1f */
/* R_ZEROES */
0, "Lb1+4*=", /* 0x20 */
1, "Ld1+=", /* 0x21 */
/* R_UNINIT */
0, "Lb1+4*=", /* 0x22 */
1, "Ld1+=", /* 0x23 */
/* R_RELOCATION */
0, "L4=", /* 0x24 */
/* R_DATA_ONE_SYMBOL */
0, "L4=Sb=", /* 0x25 */
1, "L4=Sd=", /* 0x26 */
/* R_DATA_PLEBEL */
0, "L4=Sb=", /* 0x27 */
1, "L4=Sd=", /* 0x28 */
/* R_SPACE_REF */
0, "L4=", /* 0x29 */
/* R_REPEATED_INIT */
0, "L4=Mb1+4*=", /* 0x2a */
1, "Lb4*=Mb1+L*=", /* 0x2b */
2, "Lb4*=Md1+4*=", /* 0x2c */
3, "Ld1+=Me1+=", /* 0x2d */
/* R_RESERVED */
0, "", /* 0x2e */
0, "", /* 0x2f */
/* R_PCREL_CALL */
0, "L4=RD=Sb=", /* 0x30 */
1, "L4=RD=Sb=", /* 0x31 */
2, "L4=RD=Sb=", /* 0x32 */
3, "L4=RD=Sb=", /* 0x33 */
4, "L4=RD=Sb=", /* 0x34 */
5, "L4=RD=Sb=", /* 0x35 */
6, "L4=RD=Sb=", /* 0x36 */
7, "L4=RD=Sb=", /* 0x37 */
8, "L4=RD=Sb=", /* 0x38 */
9, "L4=RD=Sb=", /* 0x39 */
0, "L4=RD8<b+=Sb=",/* 0x3a */
1, "L4=RD8<b+=Sb=",/* 0x3b */
0, "L4=RD8<b+=Sd=",/* 0x3c */
1, "L4=RD8<b+=Sd=",/* 0x3d */
/* R_RESERVED */
0, "", /* 0x3e */
0, "", /* 0x3f */
/* R_ABS_CALL */
0, "L4=RD=Sb=", /* 0x40 */
1, "L4=RD=Sb=", /* 0x41 */
2, "L4=RD=Sb=", /* 0x42 */
3, "L4=RD=Sb=", /* 0x43 */
4, "L4=RD=Sb=", /* 0x44 */
5, "L4=RD=Sb=", /* 0x45 */
6, "L4=RD=Sb=", /* 0x46 */
7, "L4=RD=Sb=", /* 0x47 */
8, "L4=RD=Sb=", /* 0x48 */
9, "L4=RD=Sb=", /* 0x49 */
0, "L4=RD8<b+=Sb=",/* 0x4a */
1, "L4=RD8<b+=Sb=",/* 0x4b */
0, "L4=RD8<b+=Sd=",/* 0x4c */
1, "L4=RD8<b+=Sd=",/* 0x4d */
/* R_RESERVED */
0, "", /* 0x4e */
0, "", /* 0x4f */
/* R_DP_RELATIVE */
0, "L4=SD=", /* 0x50 */
1, "L4=SD=", /* 0x51 */
2, "L4=SD=", /* 0x52 */
3, "L4=SD=", /* 0x53 */
4, "L4=SD=", /* 0x54 */
5, "L4=SD=", /* 0x55 */
6, "L4=SD=", /* 0x56 */
7, "L4=SD=", /* 0x57 */
8, "L4=SD=", /* 0x58 */
9, "L4=SD=", /* 0x59 */
10, "L4=SD=", /* 0x5a */
11, "L4=SD=", /* 0x5b */
12, "L4=SD=", /* 0x5c */
13, "L4=SD=", /* 0x5d */
14, "L4=SD=", /* 0x5e */
15, "L4=SD=", /* 0x5f */
16, "L4=SD=", /* 0x60 */
17, "L4=SD=", /* 0x61 */
18, "L4=SD=", /* 0x62 */
19, "L4=SD=", /* 0x63 */
20, "L4=SD=", /* 0x64 */
21, "L4=SD=", /* 0x65 */
22, "L4=SD=", /* 0x66 */
23, "L4=SD=", /* 0x67 */
24, "L4=SD=", /* 0x68 */
25, "L4=SD=", /* 0x69 */
26, "L4=SD=", /* 0x6a */
27, "L4=SD=", /* 0x6b */
28, "L4=SD=", /* 0x6c */
29, "L4=SD=", /* 0x6d */
30, "L4=SD=", /* 0x6e */
31, "L4=SD=", /* 0x6f */
32, "L4=Sb=", /* 0x70 */
33, "L4=Sd=", /* 0x71 */
/* R_RESERVED */
0, "", /* 0x72 */
0, "", /* 0x73 */
0, "", /* 0x74 */
0, "", /* 0x75 */
0, "", /* 0x76 */
0, "", /* 0x77 */
/* R_DLT_REL */
0, "L4=Sb=", /* 0x78 */
1, "L4=Sd=", /* 0x79 */
/* R_RESERVED */
0, "", /* 0x7a */
0, "", /* 0x7b */
0, "", /* 0x7c */
0, "", /* 0x7d */
0, "", /* 0x7e */
0, "", /* 0x7f */
/* R_CODE_ONE_SYMBOL */
0, "L4=SD=", /* 0x80 */
1, "L4=SD=", /* 0x81 */
2, "L4=SD=", /* 0x82 */
3, "L4=SD=", /* 0x83 */
4, "L4=SD=", /* 0x84 */
5, "L4=SD=", /* 0x85 */
6, "L4=SD=", /* 0x86 */
7, "L4=SD=", /* 0x87 */
8, "L4=SD=", /* 0x88 */
9, "L4=SD=", /* 0x89 */
10, "L4=SD=", /* 0x8q */
11, "L4=SD=", /* 0x8b */
12, "L4=SD=", /* 0x8c */
13, "L4=SD=", /* 0x8d */
14, "L4=SD=", /* 0x8e */
15, "L4=SD=", /* 0x8f */
16, "L4=SD=", /* 0x90 */
17, "L4=SD=", /* 0x91 */
18, "L4=SD=", /* 0x92 */
19, "L4=SD=", /* 0x93 */
20, "L4=SD=", /* 0x94 */
21, "L4=SD=", /* 0x95 */
22, "L4=SD=", /* 0x96 */
23, "L4=SD=", /* 0x97 */
24, "L4=SD=", /* 0x98 */
25, "L4=SD=", /* 0x99 */
26, "L4=SD=", /* 0x9a */
27, "L4=SD=", /* 0x9b */
28, "L4=SD=", /* 0x9c */
29, "L4=SD=", /* 0x9d */
30, "L4=SD=", /* 0x9e */
31, "L4=SD=", /* 0x9f */
32, "L4=Sb=", /* 0xa0 */
33, "L4=Sd=", /* 0xa1 */
/* R_RESERVED */
0, "", /* 0xa2 */
0, "", /* 0xa3 */
0, "", /* 0xa4 */
0, "", /* 0xa5 */
0, "", /* 0xa6 */
0, "", /* 0xa7 */
0, "", /* 0xa8 */
0, "", /* 0xa9 */
0, "", /* 0xaa */
0, "", /* 0xab */
0, "", /* 0xac */
0, "", /* 0xad */
/* R_MILLI_REL */
0, "L4=Sb=", /* 0xae */
1, "L4=Sd=", /* 0xaf */
/* R_CODE_PLABEL */
0, "L4=Sb=", /* 0xb0 */
1, "L4=Sd=", /* 0xb1 */
/* R_BREAKPOINT */
0, "L4=", /* 0xb2 */
/* R_ENTRY */
0, "Ui=", /* 0xb3 */
1, "Uf=", /* 0xb4 */
/* R_ALT_ENTRY */
0, "", /* 0xb5 */
/* R_EXIT */
0, "", /* 0xb6 */
/* R_BEGIN_TRY */
0, "", /* 0xb7 */
/* R_END_TRY */
0, "R0=", /* 0xb8 */
1, "Rb4*=", /* 0xb9 */
2, "Rd4*=", /* 0xba */
/* R_BEGIN_BRTAB */
0, "", /* 0xbb */
/* R_END_BRTAB */
0, "", /* 0xbc */
/* R_STATEMENT */
0, "Nb=", /* 0xbd */
1, "Nc=", /* 0xbe */
2, "Nd=", /* 0xbf */
/* R_DATA_EXPR */
0, "L4=", /* 0xc0 */
/* R_CODE_EXPR */
0, "L4=", /* 0xc1 */
/* R_FSEL */
0, "", /* 0xc2 */
/* R_LSEL */
0, "", /* 0xc3 */
/* R_RSEL */
0, "", /* 0xc4 */
/* R_N_MODE */
0, "", /* 0xc5 */
/* R_S_MODE */
0, "", /* 0xc6 */
/* R_D_MODE */
0, "", /* 0xc7 */
/* R_R_MODE */
0, "", /* 0xc8 */
/* R_DATA_OVERRIDE */
0, "V0=", /* 0xc9 */
1, "Vb=", /* 0xca */
2, "Vc=", /* 0xcb */
3, "Vd=", /* 0xcc */
4, "Ve=", /* 0xcd */
/* R_TRANSLATED */
0, "", /* 0xce */
/* R_RESERVED */
0, "", /* 0xcf */
/* R_COMP1 */
0, "Ob=", /* 0xd0 */
/* R_COMP2 */
0, "Ob=Sd=", /* 0xd1 */
/* R_COMP3 */
0, "Ob=Ve=", /* 0xd2 */
/* R_PREV_FIXUP */
0, "P", /* 0xd3 */
1, "P", /* 0xd4 */
2, "P", /* 0xd5 */
3, "P", /* 0xd6 */
/* R_RESERVED */
0, "", /* 0xd7 */
0, "", /* 0xd8 */
0, "", /* 0xd9 */
0, "", /* 0xda */
0, "", /* 0xdb */
0, "", /* 0xdc */
0, "", /* 0xdd */
0, "", /* 0xde */
0, "", /* 0xdf */
0, "", /* 0xe0 */
0, "", /* 0xe1 */
0, "", /* 0xe2 */
0, "", /* 0xe3 */
0, "", /* 0xe4 */
0, "", /* 0xe5 */
0, "", /* 0xe6 */
0, "", /* 0xe7 */
0, "", /* 0xe8 */
0, "", /* 0xe9 */
0, "", /* 0xea */
0, "", /* 0xeb */
0, "", /* 0xec */
0, "", /* 0xed */
0, "", /* 0xee */
0, "", /* 0xef */
0, "", /* 0xf0 */
0, "", /* 0xf1 */
0, "", /* 0xf2 */
0, "", /* 0xf3 */
0, "", /* 0xf4 */
0, "", /* 0xf5 */
0, "", /* 0xf6 */
0, "", /* 0xf7 */
0, "", /* 0xf8 */
0, "", /* 0xf9 */
0, "", /* 0xfa */
0, "", /* 0xfb */
0, "", /* 0xfc */
0, "", /* 0xfd */
0, "", /* 0xfe */
0, "", /* 0xff */
};
static const int comp1_opcodes[] =
{
0x00,
0x40,
0x41,
0x42,
0x43,
0x44,
0x45,
0x46,
0x47,
0x48,
0x49,
0x4a,
0x4b,
0x60,
0x80,
0xa0,
0xc0,
-1
};
static const int comp2_opcodes[] =
{
0x00,
0x80,
0x82,
0xc0,
-1
};
static const int comp3_opcodes[] =
{
0x00,
0x02,
-1
};
static reloc_howto_type som_hppa_howto_table[] =
{
{R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
@ -934,44 +1371,10 @@ som_object_setup (abfd, file_hdrp, aux_hdrp)
struct header *file_hdrp;
struct som_exec_auxhdr *aux_hdrp;
{
asection *text, *data, *bss;
/* som_mkobject will set bfd_error if som_mkobject fails. */
if (som_mkobject (abfd) != true)
return 0;
/* Make the standard .text, .data, and .bss sections so that tools
which assume those names work (size for example). They will have
no contents, but the sizes and such will reflect those of the
$CODE$, $DATA$, and $BSS$ subspaces respectively.
FIXME: Should check return status from bfd_make_section calls below. */
text = bfd_make_section (abfd, ".text");
data = bfd_make_section (abfd, ".data");
bss = bfd_make_section (abfd, ".bss");
text->_raw_size = aux_hdrp->exec_tsize;
data->_raw_size = aux_hdrp->exec_dsize;
bss->_raw_size = aux_hdrp->exec_bsize;
text->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_CODE);
data->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS);
bss->flags = (SEC_ALLOC | SEC_IS_COMMON);
/* The virtual memory addresses of the sections */
text->vma = aux_hdrp->exec_tmem;
data->vma = aux_hdrp->exec_dmem;
bss->vma = aux_hdrp->exec_bfill;
/* The file offsets of the sections */
text->filepos = aux_hdrp->exec_tfile;
data->filepos = aux_hdrp->exec_dfile;
/* The file offsets of the relocation info */
text->rel_filepos = 0;
data->rel_filepos = 0;
/* Set BFD flags based on what information is available in the SOM. */
abfd->flags = NO_FLAGS;
if (! file_hdrp->entry_offset)
@ -1156,13 +1559,19 @@ setup_sections (abfd, file_hdr)
if (subspace.dup_common || subspace.is_common)
subspace_asect->flags |= SEC_IS_COMMON;
else
else if (subspace.subspace_length > 0)
subspace_asect->flags |= SEC_HAS_CONTENTS;
if (subspace.is_loadable)
subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
if (subspace.code_only)
subspace_asect->flags |= SEC_CODE;
/* Both file_loc_init_value and initialization_length will
be zero for a BSS like subspace. */
if (subspace.file_loc_init_value == 0
&& subspace.initialization_length == 0)
subspace_asect->flags &= ~(SEC_DATA | SEC_LOAD);
/* This subspace has relocations.
The fixup_request_quantity is a byte count for the number of
entries in the relocation stream; it is not the actual number
@ -1184,7 +1593,7 @@ setup_sections (abfd, file_hdr)
subspace_asect->vma = subspace.subspace_start;
subspace_asect->_cooked_size = subspace.subspace_length;
subspace_asect->_raw_size = subspace.initialization_length;
subspace_asect->_raw_size = subspace.subspace_length;
subspace_asect->alignment_power = log2 (subspace.alignment);
subspace_asect->filepos = subspace.file_loc_init_value;
}
@ -2737,14 +3146,14 @@ som_slurp_symbol_table (abfd)
switch (bufp->symbol_type)
{
case ST_ENTRY:
case ST_PRI_PROG:
case ST_SEC_PROG:
case ST_MILLICODE:
sym->symbol.flags |= BSF_FUNCTION;
sym->symbol.value &= ~0x3;
break;
case ST_PRI_PROG:
case ST_SEC_PROG:
case ST_STUB:
case ST_MILLICODE:
case ST_CODE:
sym->symbol.value &= ~0x3;
@ -2783,9 +3192,10 @@ som_slurp_symbol_table (abfd)
}
/* Mark symbols left around by the debugger. */
if (strlen (sym->symbol.name) >= 3
if (strlen (sym->symbol.name) >= 2
&& sym->symbol.name[0] == 'L'
&& (sym->symbol.name[2] == '$' || sym->symbol.name[3] == '$'))
&& (sym->symbol.name[1] == '$' || sym->symbol.name[2] == '$'
|| sym->symbol.name[3] == '$'))
sym->symbol.flags |= BSF_DEBUGGING;
/* Note increment at bottom of loop, since we skip some symbols
@ -2872,17 +3282,346 @@ som_print_symbol (ignore_abfd, afile, symbol, how)
}
}
/* Count or process variable-length SOM fixup records.
To avoid code duplication we use this code both to compute the number
of relocations requested by a stream, and to internalize the stream.
When computing the number of relocations requested by a stream the
variables rptr, section, and symbols have no meaning.
Return the number of relocations requested by the fixup stream. When
not just counting
This needs at least two or three more passes to get it cleaned up. */
static unsigned int
som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
unsigned char *fixup;
unsigned int end;
arelent *internal_relocs;
asection *section;
asymbol **symbols;
boolean just_count;
{
unsigned int op, varname;
unsigned char *end_fixups = &fixup[end];
const struct fixup_format *fp;
char *cp;
unsigned char *save_fixup;
int variables[26], stack[20], c, v, count, prev_fixup, *sp;
const int *subop;
arelent *rptr= internal_relocs;
unsigned int offset = just_count ? 0 : section->vma;
#define var(c) variables[(c) - 'A']
#define push(v) (*sp++ = (v))
#define pop() (*--sp)
#define emptystack() (sp == stack)
som_initialize_reloc_queue (reloc_queue);
bzero (variables, sizeof (variables));
bzero (stack, sizeof (stack));
count = 0;
prev_fixup = 0;
sp = stack;
while (fixup < end_fixups)
{
/* Save pointer to the start of this fixup. We'll use
it later to determine if it is necessary to put this fixup
on the queue. */
save_fixup = fixup;
/* Get the fixup code and its associated format. */
op = *fixup++;
fp = &som_fixup_formats[op];
/* Handle a request for a previous fixup. */
if (*fp->format == 'P')
{
/* Get pointer to the beginning of the prev fixup, move
the repeated fixup to the head of the queue. */
fixup = reloc_queue[fp->D].reloc;
som_reloc_queue_fix (reloc_queue, fp->D);
prev_fixup = 1;
/* Get the fixup code and its associated format. */
op = *fixup++;
fp = &som_fixup_formats[op];
}
/* If we are not just counting, set some reasonable defaults. */
if (! just_count)
{
rptr->address = offset;
rptr->howto = &som_hppa_howto_table[op];
rptr->addend = 0;
}
/* Set default input length to 0. Get the opcode class index
into D. */
var ('L') = 0;
var ('D') = fp->D;
/* Get the opcode format. */
cp = fp->format;
/* Process the format string. Parsing happens in two phases,
parse RHS, then assign to LHS. Repeat until no more
characters in the format string. */
while (*cp)
{
/* The variable this pass is going to compute a value for. */
varname = *cp++;
/* Start processing RHS. Continue until a NULL or '=' is found. */
do
{
c = *cp++;
/* If this is a variable, push it on the stack. */
if (isupper (c))
push (var (c));
/* If this is a lower case letter, then it represents
additional data from the fixup stream to be pushed onto
the stack. */
else if (islower (c))
{
for (v = 0; c > 'a'; --c)
v = (v << 8) | *fixup++;
push (v);
}
/* A decimal constant. Push it on the stack. */
else if (isdigit (c))
{
v = c - '0';
while (isdigit (*cp))
v = (v * 10) + (*cp++ - '0');
push (v);
}
else
/* An operator. Pop two two values from the stack and
use them as operands to the given operation. Push
the result of the operation back on the stack. */
switch (c)
{
case '+':
v = pop ();
v += pop ();
push (v);
break;
case '*':
v = pop ();
v *= pop ();
push (v);
break;
case '<':
v = pop ();
v = pop () << v;
push (v);
break;
default:
abort ();
}
}
while (*cp && *cp != '=');
/* Move over the equal operator. */
cp++;
/* Pop the RHS off the stack. */
c = pop ();
/* Perform the assignment. */
var (varname) = c;
/* Handle side effects. and special 'O' stack cases. */
switch (varname)
{
/* Consume some bytes from the input space. */
case 'L':
offset += c;
break;
/* A symbol to use in the relocation. Make a note
of this if we are not just counting. */
case 'S':
if (! just_count)
rptr->sym_ptr_ptr = &symbols[c];
break;
/* Handle the linker expression stack. */
case 'O':
switch (op)
{
case R_COMP1:
subop = comp1_opcodes;
break;
case R_COMP2:
subop = comp2_opcodes;
break;
case R_COMP3:
subop = comp3_opcodes;
break;
default:
abort ();
}
while (*subop <= (unsigned char) c)
++subop;
--subop;
break;
default:
break;
}
}
/* If we used a previous fixup, clean up after it. */
if (prev_fixup)
{
fixup = save_fixup + 1;
prev_fixup = 0;
}
/* Queue it. */
else if (fixup > save_fixup + 1)
som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
/* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION
fixups to BFD. */
if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
&& som_hppa_howto_table[op].type != R_NO_RELOCATION)
{
/* Done with a single reloction. Loop back to the top. */
if (! just_count)
{
rptr->addend = var ('V');
rptr++;
}
count++;
/* Now that we've handled a "full" relocation, reset
some state. */
bzero (variables, sizeof (variables));
bzero (stack, sizeof (stack));
}
}
return count;
#undef var
#undef push
#undef pop
#undef emptystack
}
/* Read in the relocs (aka fixups in SOM terms) for a section.
som_get_reloc_upper_bound calls this routine with JUST_COUNT
set to true to indicate it only needs a count of the number
of actual relocations. */
static boolean
som_slurp_reloc_table (abfd, section, symbols, just_count)
bfd *abfd;
asection *section;
asymbol **symbols;
boolean just_count;
{
char *external_relocs;
unsigned int fixup_stream_size;
arelent *internal_relocs;
unsigned int num_relocs;
fixup_stream_size = som_section_data (section)->reloc_size;
/* If there were no relocations, then there is nothing to do. */
if (section->reloc_count == 0)
return true;
/* If reloc_count is -1, then the relocation stream has not been
parsed. We must do so now to know how many relocations exist. */
if (section->reloc_count == -1)
{
external_relocs = (char *) bfd_zalloc (abfd, fixup_stream_size);
if (external_relocs == (char *) NULL)
{
bfd_error = no_memory;
return false;
}
/* Read in the external forms. */
if (bfd_seek (abfd,
obj_som_reloc_filepos (abfd) + section->rel_filepos,
SEEK_SET)
!= 0)
{
bfd_error = system_call_error;
return false;
}
if (bfd_read (external_relocs, 1, fixup_stream_size, abfd)
!= fixup_stream_size)
{
bfd_error = system_call_error;
return false;
}
/* Let callers know how many relocations found.
also save the relocation stream as we will
need it again. */
section->reloc_count = som_set_reloc_info (external_relocs,
fixup_stream_size,
NULL, NULL, NULL, true);
som_section_data (section)->reloc_stream = external_relocs;
}
/* If the caller only wanted a count, then return now. */
if (just_count)
return true;
num_relocs = section->reloc_count;
external_relocs = som_section_data (section)->reloc_stream;
/* Return saved information about the relocations if it is available. */
if (section->relocation != (arelent *) NULL)
return true;
internal_relocs = (arelent *) bfd_zalloc (abfd,
num_relocs * sizeof (arelent));
if (internal_relocs == (arelent *) NULL)
{
bfd_error = no_memory;
return false;
}
/* Process and internalize the relocations. */
som_set_reloc_info (external_relocs, fixup_stream_size,
internal_relocs, section, symbols, false);
/* Save our results and return success. */
section->relocation = internal_relocs;
return (true);
}
/* Return the number of bytes required to store the relocation
information associated with the given section. */
static unsigned int
som_get_reloc_upper_bound (abfd, asect)
bfd *abfd;
sec_ptr asect;
{
fprintf (stderr, "som_get_reloc_upper_bound unimplemented\n");
fflush (stderr);
abort ();
return (0);
/* If section has relocations, then read in the relocation stream
and parse it to determine how many relocations exist. */
if (asect->flags & SEC_RELOC)
{
if (som_slurp_reloc_table (abfd, asect, NULL, true))
return (asect->reloc_count + 1) * sizeof (arelent);
}
/* Either there are no relocations or an error occurred while
reading and parsing the relocation stream. */
return 0;
}
/* Convert relocations from SOM (external) form into BFD internal
form. Return the number of relocations. */
static unsigned int
som_canonicalize_reloc (abfd, section, relptr, symbols)
bfd *abfd;
@ -2890,9 +3629,22 @@ som_canonicalize_reloc (abfd, section, relptr, symbols)
arelent **relptr;
asymbol **symbols;
{
fprintf (stderr, "som_canonicalize_reloc unimplemented\n");
fflush (stderr);
abort ();
arelent *tblptr;
int count;
if (som_slurp_reloc_table (abfd, section, symbols, false) == false)
return 0;
count = section->reloc_count;
tblptr = section->relocation;
if (tblptr == (arelent *) NULL)
return 0;
while (count--)
*relptr++ = tblptr++;
*relptr = (arelent *) NULL;
return section->reloc_count;
}
extern bfd_target som_vec;